]> git.proxmox.com Git - mirror_edk2.git/blame - CryptoPkg/Library/BaseCryptLib/Pk/CryptRsa.c
Update CryptoPkg for new ciphers (HMAC, Block Cipher, etc) supports.
[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
4Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
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
63 If RsaContext is NULL, then ASSERT().\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
a8c44645 74 ASSERT (RsaContext != NULL);\r
75\r
97f98500
HT
76 //\r
77 // Free OpenSSL RSA Context\r
78 //\r
79 RSA_free ((RSA *)RsaContext);\r
80}\r
81\r
97f98500 82/**\r
a8c44645 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
97f98500
HT
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
a8c44645 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
97f98500 99\r
a8c44645 100 @retval TRUE RSA key component was set successfully.\r
101 @retval FALSE Invalid RSA key component tag.\r
97f98500
HT
102\r
103**/\r
104BOOLEAN\r
105EFIAPI\r
106RsaSetKey (\r
a8c44645 107 IN OUT VOID *RsaContext,\r
108 IN RSA_KEY_TAG KeyTag,\r
109 IN CONST UINT8 *BigNumber,\r
110 IN UINTN BnSize\r
97f98500
HT
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
a8c44645 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
97f98500
HT
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
a8c44645 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
97f98500
HT
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
a8c44645 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
97f98500
HT
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
a8c44645 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
97f98500
HT
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
a8c44645 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
97f98500
HT
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
a8c44645 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
97f98500
HT
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
a8c44645 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
97f98500
HT
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
a8c44645 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
274BOOLEAN\r
275EFIAPI\r
276RsaGetKey (\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
97f98500
HT
374 break;\r
375\r
376 default:\r
377 return FALSE;\r
378 }\r
379\r
a8c44645 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
415BOOLEAN\r
416EFIAPI\r
417RsaGenerateKey (\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
462BOOLEAN\r
463EFIAPI\r
464RsaCheckKey (\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
97f98500
HT
482 return TRUE;\r
483}\r
484\r
a8c44645 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
495UINTN\r
496DigestInfoEncoding (\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
563BOOLEAN\r
564EFIAPI\r
565RsaPkcs1Sign (\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
97f98500
HT
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
a8c44645 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
97f98500
HT
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
a8c44645 622 @param[in] HashSize Size of the message hash in bytes.\r
97f98500 623 @param[in] Signature Pointer to RSA PKCS1-v1_5 signature to be verified.\r
a8c44645 624 @param[in] SigSize Size of signature in bytes.\r
97f98500 625\r
a8c44645 626 @retval TRUE Valid signature encoded in PKCS1-v1_5.\r
627 @retval FALSE Invalid signature or invalid RSA context.\r
97f98500
HT
628\r
629**/\r
630BOOLEAN\r
631EFIAPI\r
632RsaPkcs1Verify (\r
633 IN VOID *RsaContext,\r
634 IN CONST UINT8 *MessageHash,\r
a8c44645 635 IN UINTN HashSize,\r
97f98500 636 IN UINT8 *Signature,\r
a8c44645 637 IN UINTN SigSize\r
97f98500
HT
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
a8c44645 650 // ASSERT if unsupported hash size:\r
97f98500
HT
651 // Only MD5, SHA-1 or SHA-256 digest size is supported\r
652 //\r
a8c44645 653 ASSERT ((HashSize == MD5_DIGEST_SIZE) || (HashSize == SHA1_DIGEST_SIZE) ||\r
654 (HashSize == SHA256_DIGEST_SIZE));\r
97f98500
HT
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
a8c44645 660 (UINT32) SigSize,\r
97f98500
HT
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
a8c44645 669 // NOTE: Length should be the addition of HashSize and some DER value.\r
97f98500
HT
670 // Ignore more strict length checking here.\r
671 //\r
a8c44645 672 if (Length < (INTN) HashSize) {\r
97f98500
HT
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
a8c44645 686 if (CompareMem (MessageHash, Signature + Length - HashSize, HashSize) == 0) {\r
97f98500
HT
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