2 RSA Asymmetric Cipher Wrapper Implementation over OpenSSL.
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "InternalCryptLib.h"
17 #include <openssl/rsa.h>
18 #include <openssl/err.h>
21 // ASN.1 value for Hash Algorithm ID with the Distringuished Encoding Rules (DER)
22 // Refer to Section 9.2 of PKCS#1 v2.1
24 CONST UINT8 Asn1IdMd5
[] = {
25 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,
26 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
29 CONST UINT8 Asn1IdSha1
[] = {
30 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
31 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
34 CONST UINT8 Asn1IdSha256
[] = {
35 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
36 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
42 Allocates and initializes one RSA context for subsequent use.
44 @return Pointer to the RSA context that has been initialized.
45 If the allocations fails, RsaNew() returns NULL.
55 // Allocates & Initializes RSA Context by OpenSSL RSA_new()
57 return (VOID
*)RSA_new ();
61 Release the specified RSA context.
63 If RsaContext is NULL, then ASSERT().
65 @param[in] RsaContext Pointer to the RSA context to be released.
74 ASSERT (RsaContext
!= NULL
);
77 // Free OpenSSL RSA Context
79 RSA_free ((RSA
*)RsaContext
);
83 Sets the tag-designated key component into the established RSA context.
85 This function sets the tag-designated RSA key component into the established
86 RSA context from the user-specified non-negative integer (octet string format
87 represented in RSA PKCS#1).
88 If BigNumber is NULL, then the specified key componenet in RSA context is cleared.
90 If RsaContext is NULL, then ASSERT().
92 @param[in, out] RsaContext Pointer to RSA context being set.
93 @param[in] KeyTag Tag of RSA key component being set.
94 @param[in] BigNumber Pointer to octet integer buffer.
95 If NULL, then the specified key componenet in RSA
97 @param[in] BnSize Size of big number buffer in bytes.
98 If BigNumber is NULL, then it is ignored.
100 @retval TRUE RSA key component was set successfully.
101 @retval FALSE Invalid RSA key component tag.
107 IN OUT VOID
*RsaContext
,
108 IN RSA_KEY_TAG KeyTag
,
109 IN CONST UINT8
*BigNumber
,
116 // ASSERT if RsaContext is NULL
118 ASSERT (RsaContext
!= NULL
);
121 RsaKey
= (RSA
*)RsaContext
;
123 // Set RSA Key Components by converting octet string to OpenSSL BN representation.
124 // NOTE: For RSA public key (used in signature verification), only public components
125 // (N, e) are needed.
130 // RSA Public Modulus (N)
133 if (RsaKey
->n
!= NULL
) {
137 if (BigNumber
== NULL
) {
140 RsaKey
->n
= BN_bin2bn (BigNumber
, (UINT32
) BnSize
, RsaKey
->n
);
144 // RSA Public Exponent (e)
147 if (RsaKey
->e
!= NULL
) {
151 if (BigNumber
== NULL
) {
154 RsaKey
->e
= BN_bin2bn (BigNumber
, (UINT32
) BnSize
, RsaKey
->e
);
158 // RSA Private Exponent (d)
161 if (RsaKey
->d
!= NULL
) {
165 if (BigNumber
== NULL
) {
168 RsaKey
->d
= BN_bin2bn (BigNumber
, (UINT32
) BnSize
, RsaKey
->d
);
172 // RSA Secret Prime Factor of Modulus (p)
175 if (RsaKey
->p
!= NULL
) {
179 if (BigNumber
== NULL
) {
182 RsaKey
->p
= BN_bin2bn (BigNumber
, (UINT32
) BnSize
, RsaKey
->p
);
186 // RSA Secret Prime Factor of Modules (q)
189 if (RsaKey
->q
!= NULL
) {
193 if (BigNumber
== NULL
) {
196 RsaKey
->q
= BN_bin2bn (BigNumber
, (UINT32
) BnSize
, RsaKey
->q
);
200 // p's CRT Exponent (== d mod (p - 1))
203 if (RsaKey
->dmp1
!= NULL
) {
204 BN_free (RsaKey
->dmp1
);
207 if (BigNumber
== NULL
) {
210 RsaKey
->dmp1
= BN_bin2bn (BigNumber
, (UINT32
) BnSize
, RsaKey
->dmp1
);
214 // q's CRT Exponent (== d mod (q - 1))
217 if (RsaKey
->dmq1
!= NULL
) {
218 BN_free (RsaKey
->dmq1
);
221 if (BigNumber
== NULL
) {
224 RsaKey
->dmq1
= BN_bin2bn (BigNumber
, (UINT32
) BnSize
, RsaKey
->dmq1
);
228 // The CRT Coefficient (== 1/q mod p)
231 if (RsaKey
->iqmp
!= NULL
) {
232 BN_free (RsaKey
->iqmp
);
235 if (BigNumber
== NULL
) {
238 RsaKey
->iqmp
= BN_bin2bn (BigNumber
, (UINT32
) BnSize
, RsaKey
->iqmp
);
249 Gets the tag-designated RSA key component from the established RSA context.
251 This function retrieves the tag-designated RSA key component from the
252 established RSA context as a non-negative integer (octet string format
253 represented in RSA PKCS#1).
254 If specified key component has not been set or has been cleared, then returned
256 If the BigNumber buffer is too small to hold the contents of the key, FALSE
257 is returned and BnSize is set to the required buffer size to obtain the key.
259 If RsaContext is NULL, then ASSERT().
260 If BnSize is NULL, then ASSERT().
261 If BnSize is large enough but BigNumber is NULL, then ASSERT().
263 @param[in, out] RsaContext Pointer to RSA context being set.
264 @param[in] KeyTag Tag of RSA key component being set.
265 @param[out] BigNumber Pointer to octet integer buffer.
266 @param[in, out] BnSize On input, the size of big number buffer in bytes.
267 On output, the size of data returned in big number buffer in bytes.
269 @retval TRUE RSA key component was retrieved successfully.
270 @retval FALSE Invalid RSA key component tag.
271 @retval FALSE BnSize is too small.
277 IN OUT VOID
*RsaContext
,
278 IN RSA_KEY_TAG KeyTag
,
279 OUT UINT8
*BigNumber
,
287 ASSERT (RsaContext
!= NULL
);
288 ASSERT (BnSize
!= NULL
);
290 RsaKey
= (RSA
*) RsaContext
;
297 // RSA Public Modulus (N)
300 if (RsaKey
->n
== NULL
) {
307 // RSA Public Exponent (e)
310 if (RsaKey
->e
== NULL
) {
317 // RSA Private Exponent (d)
320 if (RsaKey
->d
== NULL
) {
327 // RSA Secret Prime Factor of Modulus (p)
330 if (RsaKey
->p
== NULL
) {
337 // RSA Secret Prime Factor of Modules (q)
340 if (RsaKey
->q
== NULL
) {
347 // p's CRT Exponent (== d mod (p - 1))
350 if (RsaKey
->dmp1
== NULL
) {
353 BnKey
= RsaKey
->dmp1
;
357 // q's CRT Exponent (== d mod (q - 1))
360 if (RsaKey
->dmq1
== NULL
) {
363 BnKey
= RsaKey
->dmq1
;
367 // The CRT Coefficient (== 1/q mod p)
370 if (RsaKey
->iqmp
== NULL
) {
373 BnKey
= RsaKey
->iqmp
;
381 Size
= BN_num_bytes (BnKey
);
383 if (*BnSize
< Size
) {
388 ASSERT (BigNumber
!= NULL
);
389 *BnSize
= BN_bn2bin (BnKey
, BigNumber
) ;
395 Generates RSA key components.
397 This function generates RSA key components. It takes RSA public exponent E and
398 length in bits of RSA modulus N as input, and generates all key components.
399 If PublicExponent is NULL, the default RSA public exponent (0x10001) will be used.
401 Before this function can be invoked, pseudorandom number generator must be correctly
402 initialized by RandomSeed().
404 If RsaContext is NULL, then ASSERT().
406 @param[in, out] RsaContext Pointer to RSA context being set.
407 @param[in] ModulusLength Length of RSA modulus N in bits.
408 @param[in] PublicExponent Pointer to RSA public exponent.
409 @param[in] PublicExponentSize Size of RSA public exponent buffer in bytes.
411 @retval TRUE RSA key component was generated successfully.
412 @retval FALSE Invalid RSA key component tag.
418 IN OUT VOID
*RsaContext
,
419 IN UINTN ModulusLength
,
420 IN CONST UINT8
*PublicExponent
,
421 IN UINTN PublicExponentSize
427 ASSERT (RsaContext
!= NULL
);
430 if (PublicExponent
== NULL
) {
431 BN_set_word (KeyE
, 0x10001);
433 BN_bin2bn (PublicExponent
, (UINT32
) PublicExponentSize
, KeyE
);
437 if (RSA_generate_key_ex ((RSA
*) RsaContext
, (UINT32
) ModulusLength
, KeyE
, NULL
) == 1) {
446 Validates key components of RSA context.
448 This function validates key compoents of RSA context in following aspects:
449 - Whether p is a prime
450 - Whether q is a prime
452 - Whether d*e = 1 mod lcm(p-1,q-1)
454 If RsaContext is NULL, then ASSERT().
456 @param[in] RsaContext Pointer to RSA context to check.
458 @retval TRUE RSA key components are valid.
459 @retval FALSE RSA key components are not valid.
470 ASSERT (RsaContext
!= NULL
);
472 if (RSA_check_key ((RSA
*) RsaContext
) != 1) {
473 Reason
= ERR_GET_REASON (ERR_peek_last_error ());
474 if (Reason
== RSA_R_P_NOT_PRIME
||
475 Reason
== RSA_R_Q_NOT_PRIME
||
476 Reason
== RSA_R_N_DOES_NOT_EQUAL_P_Q
||
477 Reason
== RSA_R_D_E_NOT_CONGRUENT_TO_1
) {
486 Performs the PKCS1-v1_5 encoding methods defined in RSA PKCS #1.
488 @param Message Message buffer to be encoded.
489 @param MessageSize Size of message buffer in bytes.
490 @param DigestInfo Pointer to buffer of digest info for output.
492 @return Size of DigestInfo in bytes.
497 IN CONST UINT8
*Message
,
498 IN UINTN MessageSize
,
499 OUT UINT8
*DigestInfo
502 CONST UINT8
*HashDer
;
505 ASSERT (Message
!= NULL
);
506 ASSERT (DigestInfo
!= NULL
);
509 // The original message length is used to determine the hash algorithm since
510 // message is digest value hashed by the specified algorithm.
512 switch (MessageSize
) {
513 case MD5_DIGEST_SIZE
:
515 DerSize
= sizeof (Asn1IdMd5
);
518 case SHA1_DIGEST_SIZE
:
519 HashDer
= Asn1IdSha1
;
520 DerSize
= sizeof (Asn1IdSha1
);
523 case SHA256_DIGEST_SIZE
:
524 HashDer
= Asn1IdSha256
;
525 DerSize
= sizeof (Asn1IdSha256
);
532 CopyMem (DigestInfo
, HashDer
, DerSize
);
533 CopyMem (DigestInfo
+ DerSize
, Message
, MessageSize
);
535 return (DerSize
+ MessageSize
);
539 Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme.
541 This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme defined in
543 If the Signature buffer is too small to hold the contents of signature, FALSE
544 is returned and SigSize is set to the required buffer size to obtain the signature.
546 If RsaContext is NULL, then ASSERT().
547 If MessageHash is NULL, then ASSERT().
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().
549 If SigSize is large enough but Signature is NULL, then ASSERT().
551 @param[in] RsaContext Pointer to RSA context for signature generation.
552 @param[in] MessageHash Pointer to octet message hash to be signed.
553 @param[in] HashSize Size of the message hash in bytes.
554 @param[out] Signature Pointer to buffer to receive RSA PKCS1-v1_5 signature.
555 @param[in, out] SigSize On input, the size of Signature buffer in bytes.
556 On output, the size of data returned in Signature buffer in bytes.
558 @retval TRUE Signature successfully generated in PKCS1-v1_5.
559 @retval FALSE Signature generation failed.
560 @retval FALSE SigSize is too small.
567 IN CONST UINT8
*MessageHash
,
569 OUT UINT8
*Signature
,
570 IN OUT UINTN
*SigSize
577 ASSERT (RsaContext
!= NULL
);
578 ASSERT (MessageHash
!= NULL
);
579 ASSERT ((HashSize
== MD5_DIGEST_SIZE
) ||
580 (HashSize
== SHA1_DIGEST_SIZE
) ||
581 (HashSize
== SHA256_DIGEST_SIZE
));
583 Rsa
= (RSA
*) RsaContext
;
584 Size
= BN_num_bytes (Rsa
->n
);
586 if (*SigSize
< Size
) {
591 ASSERT (Signature
!= NULL
);
593 Size
= DigestInfoEncoding (MessageHash
, HashSize
, Signature
);
595 ReturnVal
= RSA_private_encrypt (
603 if (ReturnVal
< (INTN
) Size
) {
607 *SigSize
= (UINTN
)ReturnVal
;
612 Verifies the RSA-SSA signature with EMSA-PKCS1-v1_5 encoding scheme defined in
615 If RsaContext is NULL, then ASSERT().
616 If MessageHash is NULL, then ASSERT().
617 If Signature is NULL, then ASSERT().
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().
620 @param[in] RsaContext Pointer to RSA context for signature verification.
621 @param[in] MessageHash Pointer to octet message hash to be checked.
622 @param[in] HashSize Size of the message hash in bytes.
623 @param[in] Signature Pointer to RSA PKCS1-v1_5 signature to be verified.
624 @param[in] SigSize Size of signature in bytes.
626 @retval TRUE Valid signature encoded in PKCS1-v1_5.
627 @retval FALSE Invalid signature or invalid RSA context.
634 IN CONST UINT8
*MessageHash
,
643 // ASSERT if RsaContext, MessageHash or Signature is NULL
645 ASSERT (RsaContext
!= NULL
);
646 ASSERT (MessageHash
!= NULL
);
647 ASSERT (Signature
!= NULL
);
650 // ASSERT if unsupported hash size:
651 // Only MD5, SHA-1 or SHA-256 digest size is supported
653 ASSERT ((HashSize
== MD5_DIGEST_SIZE
) || (HashSize
== SHA1_DIGEST_SIZE
) ||
654 (HashSize
== SHA256_DIGEST_SIZE
));
657 // RSA PKCS#1 Signature Decoding using OpenSSL RSA Decryption with Public Key
659 Length
= RSA_public_decrypt (
668 // Invalid RSA Key or PKCS#1 Padding Checking Failed (if Length < 0)
669 // NOTE: Length should be the addition of HashSize and some DER value.
670 // Ignore more strict length checking here.
672 if (Length
< (INTN
) HashSize
) {
677 // Validate the MessageHash and Decoded Signature
678 // NOTE: The decoded Signature should be the DER encoding of the DigestInfo value
679 // DigestInfo ::= SEQUENCE {
680 // digestAlgorithm AlgorithmIdentifier
681 // digest OCTET STRING
683 // Then Memory Comparing should skip the DER value of the underlying SEQUENCE
684 // type and AlgorithmIdentifier.
686 if (CompareMem (MessageHash
, Signature
+ Length
- HashSize
, HashSize
) == 0) {
688 // Valid RSA PKCS#1 Signature
693 // Failed to verification