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