]> git.proxmox.com Git - mirror_edk2.git/blame - CryptoPkg/Library/BaseCryptLib/Pk/CryptRsa.c
1. Remove conducting ASSERT in BaseCryptLib.
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Pk / CryptRsa.c
CommitLineData
97f98500
HT
1/** @file\r
2 RSA Asymmetric Cipher Wrapper Implementation over OpenSSL.\r
3\r
16d2c32c 4Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
97f98500
HT
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
a8c44645 15#include "InternalCryptLib.h"\r
97f98500 16\r
97f98500 17#include <openssl/rsa.h>\r
a8c44645 18#include <openssl/err.h>\r
19\r
20//\r
21// ASN.1 value for Hash Algorithm ID with the Distringuished Encoding Rules (DER)\r
22// Refer to Section 9.2 of PKCS#1 v2.1\r
23// \r
24CONST UINT8 Asn1IdMd5[] = {\r
25 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,\r
26 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10\r
27 };\r
28\r
29CONST UINT8 Asn1IdSha1[] = {\r
30 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,\r
31 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14\r
32 };\r
33\r
34CONST UINT8 Asn1IdSha256[] = {\r
35 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,\r
36 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,\r
37 0x00, 0x04, 0x20\r
38 };\r
97f98500
HT
39\r
40\r
41/**\r
a8c44645 42 Allocates and initializes one RSA context for subsequent use.\r
97f98500 43\r
a8c44645 44 @return Pointer to the RSA context that has been initialized.\r
97f98500
HT
45 If the allocations fails, RsaNew() returns NULL.\r
46\r
47**/\r
48VOID *\r
49EFIAPI\r
50RsaNew (\r
51 VOID\r
52 )\r
53{\r
54 //\r
55 // Allocates & Initializes RSA Context by OpenSSL RSA_new()\r
56 //\r
57 return (VOID *)RSA_new ();\r
58}\r
59\r
97f98500 60/**\r
a8c44645 61 Release the specified RSA context.\r
62\r
16d2c32c 63 If RsaContext is NULL, then return FALSE.\r
97f98500
HT
64\r
65 @param[in] RsaContext Pointer to the RSA context to be released.\r
66\r
67**/\r
68VOID\r
69EFIAPI\r
70RsaFree (\r
71 IN VOID *RsaContext\r
72 )\r
73{\r
74 //\r
75 // Free OpenSSL RSA Context\r
76 //\r
77 RSA_free ((RSA *)RsaContext);\r
78}\r
79\r
97f98500 80/**\r
a8c44645 81 Sets the tag-designated key component into the established RSA context.\r
82\r
83 This function sets the tag-designated RSA key component into the established\r
84 RSA context from the user-specified non-negative integer (octet string format\r
85 represented in RSA PKCS#1).\r
86 If BigNumber is NULL, then the specified key componenet in RSA context is cleared.\r
97f98500 87\r
16d2c32c 88 If RsaContext is NULL, then return FALSE.\r
97f98500
HT
89\r
90 @param[in, out] RsaContext Pointer to RSA context being set.\r
91 @param[in] KeyTag Tag of RSA key component being set.\r
92 @param[in] BigNumber Pointer to octet integer buffer.\r
a8c44645 93 If NULL, then the specified key componenet in RSA\r
94 context is cleared.\r
95 @param[in] BnSize Size of big number buffer in bytes.\r
96 If BigNumber is NULL, then it is ignored.\r
97f98500 97\r
a8c44645 98 @retval TRUE RSA key component was set successfully.\r
99 @retval FALSE Invalid RSA key component tag.\r
97f98500
HT
100\r
101**/\r
102BOOLEAN\r
103EFIAPI\r
104RsaSetKey (\r
a8c44645 105 IN OUT VOID *RsaContext,\r
106 IN RSA_KEY_TAG KeyTag,\r
107 IN CONST UINT8 *BigNumber,\r
108 IN UINTN BnSize\r
97f98500
HT
109 )\r
110{\r
111 RSA *RsaKey;\r
112\r
113 //\r
16d2c32c 114 // Check input parameters.\r
97f98500 115 //\r
16d2c32c 116 if (RsaContext == NULL) {\r
117 return FALSE;\r
118 }\r
97f98500
HT
119\r
120 RsaKey = (RSA *)RsaContext;\r
121 //\r
122 // Set RSA Key Components by converting octet string to OpenSSL BN representation.\r
123 // NOTE: For RSA public key (used in signature verification), only public components\r
124 // (N, e) are needed.\r
125 //\r
126 switch (KeyTag) {\r
127\r
128 //\r
129 // RSA Public Modulus (N)\r
130 //\r
131 case RsaKeyN:\r
132 if (RsaKey->n != NULL) {\r
133 BN_free (RsaKey->n);\r
134 }\r
a8c44645 135 RsaKey->n = NULL;\r
136 if (BigNumber == NULL) {\r
137 break;\r
138 }\r
139 RsaKey->n = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->n);\r
97f98500
HT
140 break;\r
141\r
142 //\r
143 // RSA Public Exponent (e)\r
144 //\r
145 case RsaKeyE:\r
146 if (RsaKey->e != NULL) {\r
147 BN_free (RsaKey->e);\r
148 }\r
a8c44645 149 RsaKey->e = NULL;\r
150 if (BigNumber == NULL) {\r
151 break;\r
152 }\r
153 RsaKey->e = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->e);\r
97f98500
HT
154 break;\r
155\r
156 //\r
157 // RSA Private Exponent (d)\r
158 //\r
159 case RsaKeyD:\r
160 if (RsaKey->d != NULL) {\r
161 BN_free (RsaKey->d);\r
162 }\r
a8c44645 163 RsaKey->d = NULL;\r
164 if (BigNumber == NULL) {\r
165 break;\r
166 }\r
167 RsaKey->d = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->d);\r
97f98500
HT
168 break;\r
169\r
170 //\r
171 // RSA Secret Prime Factor of Modulus (p)\r
172 //\r
173 case RsaKeyP:\r
174 if (RsaKey->p != NULL) {\r
175 BN_free (RsaKey->p);\r
176 }\r
a8c44645 177 RsaKey->p = NULL;\r
178 if (BigNumber == NULL) {\r
179 break;\r
180 }\r
181 RsaKey->p = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->p);\r
97f98500
HT
182 break;\r
183\r
184 //\r
185 // RSA Secret Prime Factor of Modules (q)\r
186 //\r
187 case RsaKeyQ:\r
188 if (RsaKey->q != NULL) {\r
189 BN_free (RsaKey->q);\r
190 }\r
a8c44645 191 RsaKey->q = NULL;\r
192 if (BigNumber == NULL) {\r
193 break;\r
194 }\r
195 RsaKey->q = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->q);\r
97f98500
HT
196 break;\r
197\r
198 //\r
199 // p's CRT Exponent (== d mod (p - 1))\r
200 //\r
201 case RsaKeyDp:\r
202 if (RsaKey->dmp1 != NULL) {\r
203 BN_free (RsaKey->dmp1);\r
204 }\r
a8c44645 205 RsaKey->dmp1 = NULL;\r
206 if (BigNumber == NULL) {\r
207 break;\r
208 }\r
209 RsaKey->dmp1 = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->dmp1);\r
97f98500
HT
210 break;\r
211\r
212 //\r
213 // q's CRT Exponent (== d mod (q - 1))\r
214 //\r
215 case RsaKeyDq:\r
216 if (RsaKey->dmq1 != NULL) {\r
217 BN_free (RsaKey->dmq1);\r
218 }\r
a8c44645 219 RsaKey->dmq1 = NULL;\r
220 if (BigNumber == NULL) {\r
221 break;\r
222 }\r
223 RsaKey->dmq1 = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->dmq1);\r
97f98500
HT
224 break;\r
225\r
226 //\r
227 // The CRT Coefficient (== 1/q mod p)\r
228 //\r
229 case RsaKeyQInv:\r
230 if (RsaKey->iqmp != NULL) {\r
231 BN_free (RsaKey->iqmp);\r
232 }\r
a8c44645 233 RsaKey->iqmp = NULL;\r
234 if (BigNumber == NULL) {\r
235 break;\r
236 }\r
237 RsaKey->iqmp = BN_bin2bn (BigNumber, (UINT32) BnSize, RsaKey->iqmp);\r
238 break;\r
239\r
240 default:\r
241 return FALSE;\r
242 }\r
243\r
244 return TRUE;\r
245}\r
246\r
247/**\r
248 Gets the tag-designated RSA key component from the established RSA context.\r
249\r
250 This function retrieves the tag-designated RSA key component from the\r
251 established RSA context as a non-negative integer (octet string format\r
252 represented in RSA PKCS#1).\r
253 If specified key component has not been set or has been cleared, then returned\r
254 BnSize is set to 0.\r
255 If the BigNumber buffer is too small to hold the contents of the key, FALSE\r
256 is returned and BnSize is set to the required buffer size to obtain the key.\r
257\r
16d2c32c 258 If RsaContext is NULL, then return FALSE.\r
259 If BnSize is NULL, then return FALSE.\r
260 If BnSize is large enough but BigNumber is NULL, then return FALSE.\r
a8c44645 261\r
262 @param[in, out] RsaContext Pointer to RSA context being set.\r
263 @param[in] KeyTag Tag of RSA key component being set.\r
264 @param[out] BigNumber Pointer to octet integer buffer.\r
265 @param[in, out] BnSize On input, the size of big number buffer in bytes.\r
266 On output, the size of data returned in big number buffer in bytes.\r
267\r
268 @retval TRUE RSA key component was retrieved successfully.\r
269 @retval FALSE Invalid RSA key component tag.\r
270 @retval FALSE BnSize is too small.\r
271\r
272**/\r
273BOOLEAN\r
274EFIAPI\r
275RsaGetKey (\r
276 IN OUT VOID *RsaContext,\r
277 IN RSA_KEY_TAG KeyTag,\r
278 OUT UINT8 *BigNumber,\r
279 IN OUT UINTN *BnSize\r
280 )\r
281{\r
282 RSA *RsaKey;\r
283 BIGNUM *BnKey;\r
284 UINTN Size;\r
285\r
16d2c32c 286 //\r
287 // Check input parameters.\r
288 //\r
289 if (RsaContext == NULL || BnSize == NULL) {\r
290 return FALSE;\r
291 }\r
a8c44645 292\r
293 RsaKey = (RSA *) RsaContext;\r
294 Size = *BnSize;\r
295 *BnSize = 0;\r
296\r
297 switch (KeyTag) {\r
298\r
299 //\r
300 // RSA Public Modulus (N)\r
301 //\r
302 case RsaKeyN:\r
303 if (RsaKey->n == NULL) {\r
304 return TRUE;\r
305 }\r
306 BnKey = RsaKey->n;\r
307 break;\r
308\r
309 //\r
310 // RSA Public Exponent (e)\r
311 //\r
312 case RsaKeyE:\r
313 if (RsaKey->e == NULL) {\r
314 return TRUE;\r
315 }\r
316 BnKey = RsaKey->e;\r
317 break;\r
318\r
319 //\r
320 // RSA Private Exponent (d)\r
321 //\r
322 case RsaKeyD:\r
323 if (RsaKey->d == NULL) {\r
324 return TRUE;\r
325 }\r
326 BnKey = RsaKey->d;\r
327 break;\r
328\r
329 //\r
330 // RSA Secret Prime Factor of Modulus (p)\r
331 //\r
332 case RsaKeyP:\r
333 if (RsaKey->p == NULL) {\r
334 return TRUE;\r
335 }\r
336 BnKey = RsaKey->p;\r
337 break;\r
338\r
339 //\r
340 // RSA Secret Prime Factor of Modules (q)\r
341 //\r
342 case RsaKeyQ:\r
343 if (RsaKey->q == NULL) {\r
344 return TRUE;\r
345 }\r
346 BnKey = RsaKey->q;\r
347 break;\r
348\r
349 //\r
350 // p's CRT Exponent (== d mod (p - 1))\r
351 //\r
352 case RsaKeyDp:\r
353 if (RsaKey->dmp1 == NULL) {\r
354 return TRUE;\r
355 }\r
356 BnKey = RsaKey->dmp1;\r
357 break;\r
358\r
359 //\r
360 // q's CRT Exponent (== d mod (q - 1))\r
361 //\r
362 case RsaKeyDq:\r
363 if (RsaKey->dmq1 == NULL) {\r
364 return TRUE;\r
365 }\r
366 BnKey = RsaKey->dmq1;\r
367 break;\r
368\r
369 //\r
370 // The CRT Coefficient (== 1/q mod p)\r
371 //\r
372 case RsaKeyQInv:\r
373 if (RsaKey->iqmp == NULL) {\r
374 return TRUE;\r
375 }\r
376 BnKey = RsaKey->iqmp;\r
97f98500
HT
377 break;\r
378\r
379 default:\r
380 return FALSE;\r
381 }\r
382\r
a8c44645 383 *BnSize = Size;\r
384 Size = BN_num_bytes (BnKey);\r
385\r
386 if (*BnSize < Size) {\r
387 *BnSize = Size;\r
388 return FALSE;\r
389 }\r
390\r
16d2c32c 391 if (BigNumber == NULL) {\r
392 return FALSE;\r
393 }\r
a8c44645 394 *BnSize = BN_bn2bin (BnKey, BigNumber) ;\r
395 \r
396 return TRUE;\r
397}\r
398\r
399/**\r
400 Generates RSA key components.\r
401\r
402 This function generates RSA key components. It takes RSA public exponent E and\r
403 length in bits of RSA modulus N as input, and generates all key components.\r
404 If PublicExponent is NULL, the default RSA public exponent (0x10001) will be used.\r
405\r
406 Before this function can be invoked, pseudorandom number generator must be correctly\r
407 initialized by RandomSeed().\r
408\r
16d2c32c 409 If RsaContext is NULL, then return FALSE.\r
a8c44645 410\r
411 @param[in, out] RsaContext Pointer to RSA context being set.\r
412 @param[in] ModulusLength Length of RSA modulus N in bits.\r
413 @param[in] PublicExponent Pointer to RSA public exponent.\r
414 @param[in] PublicExponentSize Size of RSA public exponent buffer in bytes. \r
415\r
416 @retval TRUE RSA key component was generated successfully.\r
417 @retval FALSE Invalid RSA key component tag.\r
418\r
419**/\r
420BOOLEAN\r
421EFIAPI\r
422RsaGenerateKey (\r
423 IN OUT VOID *RsaContext,\r
424 IN UINTN ModulusLength,\r
425 IN CONST UINT8 *PublicExponent,\r
426 IN UINTN PublicExponentSize\r
427 )\r
428{\r
429 BIGNUM *KeyE;\r
430 BOOLEAN RetVal;\r
431\r
16d2c32c 432 //\r
433 // Check input parameters.\r
434 //\r
435 if (RsaContext == NULL) {\r
436 return FALSE;\r
437 }\r
438 \r
a8c44645 439 KeyE = BN_new ();\r
440 if (PublicExponent == NULL) {\r
441 BN_set_word (KeyE, 0x10001);\r
442 } else {\r
443 BN_bin2bn (PublicExponent, (UINT32) PublicExponentSize, KeyE);\r
444 }\r
445\r
446 RetVal = FALSE;\r
447 if (RSA_generate_key_ex ((RSA *) RsaContext, (UINT32) ModulusLength, KeyE, NULL) == 1) {\r
448 RetVal = TRUE;\r
449 }\r
450\r
451 BN_free (KeyE);\r
452 return RetVal;\r
453}\r
454\r
455/**\r
456 Validates key components of RSA context.\r
457\r
458 This function validates key compoents of RSA context in following aspects:\r
459 - Whether p is a prime\r
460 - Whether q is a prime\r
461 - Whether n = p * q\r
462 - Whether d*e = 1 mod lcm(p-1,q-1)\r
463\r
16d2c32c 464 If RsaContext is NULL, then return FALSE.\r
a8c44645 465\r
466 @param[in] RsaContext Pointer to RSA context to check.\r
467\r
468 @retval TRUE RSA key components are valid.\r
469 @retval FALSE RSA key components are not valid.\r
470\r
471**/\r
472BOOLEAN\r
473EFIAPI\r
474RsaCheckKey (\r
475 IN VOID *RsaContext\r
476 )\r
477{\r
478 UINTN Reason;\r
479\r
16d2c32c 480 //\r
481 // Check input parameters.\r
482 //\r
483 if (RsaContext == NULL) {\r
484 return FALSE;\r
485 }\r
486 \r
a8c44645 487 if (RSA_check_key ((RSA *) RsaContext) != 1) {\r
488 Reason = ERR_GET_REASON (ERR_peek_last_error ());\r
489 if (Reason == RSA_R_P_NOT_PRIME ||\r
490 Reason == RSA_R_Q_NOT_PRIME ||\r
491 Reason == RSA_R_N_DOES_NOT_EQUAL_P_Q ||\r
492 Reason == RSA_R_D_E_NOT_CONGRUENT_TO_1) {\r
493 return FALSE;\r
494 }\r
495 }\r
496\r
97f98500
HT
497 return TRUE;\r
498}\r
499\r
a8c44645 500/**\r
501 Performs the PKCS1-v1_5 encoding methods defined in RSA PKCS #1.\r
502\r
503 @param Message Message buffer to be encoded.\r
504 @param MessageSize Size of message buffer in bytes.\r
505 @param DigestInfo Pointer to buffer of digest info for output.\r
506\r
507 @return Size of DigestInfo in bytes.\r
508\r
509**/ \r
510UINTN\r
511DigestInfoEncoding (\r
512 IN CONST UINT8 *Message,\r
513 IN UINTN MessageSize,\r
514 OUT UINT8 *DigestInfo\r
515 )\r
516{\r
517 CONST UINT8 *HashDer;\r
518 UINTN DerSize;\r
519\r
16d2c32c 520 //\r
521 // Check input parameters.\r
522 //\r
523 if (Message == NULL || DigestInfo == NULL) {\r
524 return FALSE;\r
525 }\r
a8c44645 526\r
527 //\r
528 // The original message length is used to determine the hash algorithm since\r
529 // message is digest value hashed by the specified algorithm.\r
530 //\r
531 switch (MessageSize) {\r
532 case MD5_DIGEST_SIZE:\r
533 HashDer = Asn1IdMd5;\r
534 DerSize = sizeof (Asn1IdMd5);\r
535 break;\r
536 \r
537 case SHA1_DIGEST_SIZE:\r
538 HashDer = Asn1IdSha1;\r
539 DerSize = sizeof (Asn1IdSha1);\r
540 break;\r
541 \r
542 case SHA256_DIGEST_SIZE:\r
543 HashDer = Asn1IdSha256;\r
544 DerSize = sizeof (Asn1IdSha256);\r
545 break;\r
546 \r
547 default:\r
548 return FALSE;\r
549 }\r
550\r
551 CopyMem (DigestInfo, HashDer, DerSize);\r
552 CopyMem (DigestInfo + DerSize, Message, MessageSize);\r
553\r
554 return (DerSize + MessageSize);\r
555}\r
556\r
557/**\r
558 Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme.\r
559\r
560 This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme defined in\r
561 RSA PKCS#1.\r
562 If the Signature buffer is too small to hold the contents of signature, FALSE\r
563 is returned and SigSize is set to the required buffer size to obtain the signature.\r
564\r
16d2c32c 565 If RsaContext is NULL, then return FALSE.\r
566 If MessageHash is NULL, then return FALSE.\r
567 If HashSize is not equal to the size of MD5, SHA-1 or SHA-256 digest, then return FALSE.\r
568 If SigSize is large enough but Signature is NULL, then return FALSE.\r
a8c44645 569\r
570 @param[in] RsaContext Pointer to RSA context for signature generation.\r
571 @param[in] MessageHash Pointer to octet message hash to be signed.\r
572 @param[in] HashSize Size of the message hash in bytes.\r
573 @param[out] Signature Pointer to buffer to receive RSA PKCS1-v1_5 signature.\r
574 @param[in, out] SigSize On input, the size of Signature buffer in bytes.\r
575 On output, the size of data returned in Signature buffer in bytes.\r
576\r
577 @retval TRUE Signature successfully generated in PKCS1-v1_5.\r
578 @retval FALSE Signature generation failed.\r
579 @retval FALSE SigSize is too small.\r
580\r
581**/\r
582BOOLEAN\r
583EFIAPI\r
584RsaPkcs1Sign (\r
585 IN VOID *RsaContext,\r
586 IN CONST UINT8 *MessageHash,\r
587 IN UINTN HashSize,\r
588 OUT UINT8 *Signature,\r
589 IN OUT UINTN *SigSize\r
590 )\r
591{\r
592 RSA *Rsa;\r
593 UINTN Size;\r
594 INTN ReturnVal;\r
595\r
16d2c32c 596 //\r
597 // Check input parameters.\r
598 //\r
599 if (RsaContext == NULL || MessageHash == NULL ||\r
600 (HashSize != MD5_DIGEST_SIZE && HashSize != SHA1_DIGEST_SIZE && HashSize != SHA256_DIGEST_SIZE)) {\r
601 return FALSE;\r
602 }\r
a8c44645 603\r
604 Rsa = (RSA *) RsaContext;\r
605 Size = BN_num_bytes (Rsa->n);\r
606\r
607 if (*SigSize < Size) {\r
608 *SigSize = Size;\r
609 return FALSE;\r
610 }\r
611\r
16d2c32c 612 if (Signature == NULL) {\r
613 return FALSE;\r
614 }\r
a8c44645 615\r
616 Size = DigestInfoEncoding (MessageHash, HashSize, Signature);\r
617\r
618 ReturnVal = RSA_private_encrypt (\r
619 (UINT32) Size,\r
620 Signature,\r
621 Signature,\r
622 Rsa,\r
623 RSA_PKCS1_PADDING\r
624 );\r
625\r
626 if (ReturnVal < (INTN) Size) {\r
627 return FALSE;\r
628 }\r
629\r
630 *SigSize = (UINTN)ReturnVal;\r
631 return TRUE;\r
632}\r
97f98500
HT
633\r
634/**\r
635 Verifies the RSA-SSA signature with EMSA-PKCS1-v1_5 encoding scheme defined in\r
636 RSA PKCS#1.\r
637\r
16d2c32c 638 If RsaContext is NULL, then return FALSE.\r
639 If MessageHash is NULL, then return FALSE.\r
640 If Signature is NULL, then return FALSE.\r
641 If HashSize is not equal to the size of MD5, SHA-1 or SHA-256 digest, then return FALSE.\r
97f98500
HT
642\r
643 @param[in] RsaContext Pointer to RSA context for signature verification.\r
644 @param[in] MessageHash Pointer to octet message hash to be checked.\r
a8c44645 645 @param[in] HashSize Size of the message hash in bytes.\r
97f98500 646 @param[in] Signature Pointer to RSA PKCS1-v1_5 signature to be verified.\r
a8c44645 647 @param[in] SigSize Size of signature in bytes.\r
97f98500 648\r
a8c44645 649 @retval TRUE Valid signature encoded in PKCS1-v1_5.\r
650 @retval FALSE Invalid signature or invalid RSA context.\r
97f98500
HT
651\r
652**/\r
653BOOLEAN\r
654EFIAPI\r
655RsaPkcs1Verify (\r
656 IN VOID *RsaContext,\r
657 IN CONST UINT8 *MessageHash,\r
a8c44645 658 IN UINTN HashSize,\r
97f98500 659 IN UINT8 *Signature,\r
a8c44645 660 IN UINTN SigSize\r
97f98500
HT
661 )\r
662{\r
663 INTN Length;\r
664\r
665 //\r
16d2c32c 666 // Check input parameters.\r
97f98500 667 //\r
16d2c32c 668 if (RsaContext == NULL || MessageHash == NULL || Signature == NULL) {\r
669 return FALSE;\r
670 }\r
97f98500 671\r
16d2c32c 672 \r
97f98500 673 //\r
16d2c32c 674 // Check for unsupported hash size:\r
97f98500
HT
675 // Only MD5, SHA-1 or SHA-256 digest size is supported\r
676 //\r
16d2c32c 677 if (HashSize != MD5_DIGEST_SIZE && HashSize != SHA1_DIGEST_SIZE && HashSize != SHA256_DIGEST_SIZE) {\r
678 return FALSE;\r
679 }\r
680 \r
97f98500
HT
681 //\r
682 // RSA PKCS#1 Signature Decoding using OpenSSL RSA Decryption with Public Key\r
683 //\r
684 Length = RSA_public_decrypt (\r
a8c44645 685 (UINT32) SigSize,\r
97f98500
HT
686 Signature,\r
687 Signature,\r
688 RsaContext,\r
689 RSA_PKCS1_PADDING\r
690 );\r
691\r
692 //\r
693 // Invalid RSA Key or PKCS#1 Padding Checking Failed (if Length < 0)\r
a8c44645 694 // NOTE: Length should be the addition of HashSize and some DER value.\r
97f98500
HT
695 // Ignore more strict length checking here.\r
696 //\r
a8c44645 697 if (Length < (INTN) HashSize) {\r
97f98500
HT
698 return FALSE;\r
699 }\r
700\r
701 //\r
702 // Validate the MessageHash and Decoded Signature\r
703 // NOTE: The decoded Signature should be the DER encoding of the DigestInfo value\r
704 // DigestInfo ::= SEQUENCE {\r
705 // digestAlgorithm AlgorithmIdentifier\r
706 // digest OCTET STRING\r
707 // }\r
708 // Then Memory Comparing should skip the DER value of the underlying SEQUENCE\r
709 // type and AlgorithmIdentifier.\r
710 //\r
a8c44645 711 if (CompareMem (MessageHash, Signature + Length - HashSize, HashSize) == 0) {\r
97f98500
HT
712 //\r
713 // Valid RSA PKCS#1 Signature\r
714 //\r
715 return TRUE;\r
716 } else {\r
717 //\r
718 // Failed to verification\r
719 //\r
720 return FALSE;\r
721 }\r
722}\r