REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the CryptoPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
		
			
				
	
	
		
			366 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			366 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   RSA Asymmetric Cipher Wrapper Implementation over OpenSSL.
 | |
| 
 | |
|   This file implements following APIs which provide more capabilities for RSA:
 | |
|   1) RsaGetKey
 | |
|   2) RsaGenerateKey
 | |
|   3) RsaCheckKey
 | |
|   4) RsaPkcs1Sign
 | |
| 
 | |
| Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "InternalCryptLib.h"
 | |
| 
 | |
| #include <openssl/bn.h>
 | |
| #include <openssl/rsa.h>
 | |
| #include <openssl/err.h>
 | |
| #include <openssl/objects.h>
 | |
| 
 | |
| /**
 | |
|   Gets the tag-designated RSA key component from the established RSA context.
 | |
| 
 | |
|   This function retrieves the tag-designated RSA key component from the
 | |
|   established RSA context as a non-negative integer (octet string format
 | |
|   represented in RSA PKCS#1).
 | |
|   If specified key component has not been set or has been cleared, then returned
 | |
|   BnSize is set to 0.
 | |
|   If the BigNumber buffer is too small to hold the contents of the key, FALSE
 | |
|   is returned and BnSize is set to the required buffer size to obtain the key.
 | |
| 
 | |
|   If RsaContext is NULL, then return FALSE.
 | |
|   If BnSize is NULL, then return FALSE.
 | |
|   If BnSize is large enough but BigNumber is NULL, then return FALSE.
 | |
| 
 | |
|   @param[in, out]  RsaContext  Pointer to RSA context being set.
 | |
|   @param[in]       KeyTag      Tag of RSA key component being set.
 | |
|   @param[out]      BigNumber   Pointer to octet integer buffer.
 | |
|   @param[in, out]  BnSize      On input, the size of big number buffer in bytes.
 | |
|                                On output, the size of data returned in big number buffer in bytes.
 | |
| 
 | |
|   @retval  TRUE   RSA key component was retrieved successfully.
 | |
|   @retval  FALSE  Invalid RSA key component tag.
 | |
|   @retval  FALSE  BnSize is too small.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| RsaGetKey (
 | |
|   IN OUT  VOID         *RsaContext,
 | |
|   IN      RSA_KEY_TAG  KeyTag,
 | |
|   OUT     UINT8        *BigNumber,
 | |
|   IN OUT  UINTN        *BnSize
 | |
|   )
 | |
| {
 | |
|   RSA     *RsaKey;
 | |
|   BIGNUM  *BnKey;
 | |
|   UINTN   Size;
 | |
| 
 | |
|   //
 | |
|   // Check input parameters.
 | |
|   //
 | |
|   if ((RsaContext == NULL) || (BnSize == NULL)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   RsaKey  = (RSA *)RsaContext;
 | |
|   Size    = *BnSize;
 | |
|   *BnSize = 0;
 | |
|   BnKey   = NULL;
 | |
| 
 | |
|   switch (KeyTag) {
 | |
|     //
 | |
|     // RSA Public Modulus (N)
 | |
|     //
 | |
|     case RsaKeyN:
 | |
|       RSA_get0_key (RsaKey, (const BIGNUM **)&BnKey, NULL, NULL);
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // RSA Public Exponent (e)
 | |
|     //
 | |
|     case RsaKeyE:
 | |
|       RSA_get0_key (RsaKey, NULL, (const BIGNUM **)&BnKey, NULL);
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // RSA Private Exponent (d)
 | |
|     //
 | |
|     case RsaKeyD:
 | |
|       RSA_get0_key (RsaKey, NULL, NULL, (const BIGNUM **)&BnKey);
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // RSA Secret Prime Factor of Modulus (p)
 | |
|     //
 | |
|     case RsaKeyP:
 | |
|       RSA_get0_factors (RsaKey, (const BIGNUM **)&BnKey, NULL);
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // RSA Secret Prime Factor of Modules (q)
 | |
|     //
 | |
|     case RsaKeyQ:
 | |
|       RSA_get0_factors (RsaKey, NULL, (const BIGNUM **)&BnKey);
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // p's CRT Exponent (== d mod (p - 1))
 | |
|     //
 | |
|     case RsaKeyDp:
 | |
|       RSA_get0_crt_params (RsaKey, (const BIGNUM **)&BnKey, NULL, NULL);
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // q's CRT Exponent (== d mod (q - 1))
 | |
|     //
 | |
|     case RsaKeyDq:
 | |
|       RSA_get0_crt_params (RsaKey, NULL, (const BIGNUM **)&BnKey, NULL);
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // The CRT Coefficient (== 1/q mod p)
 | |
|     //
 | |
|     case RsaKeyQInv:
 | |
|       RSA_get0_crt_params (RsaKey, NULL, NULL, (const BIGNUM **)&BnKey);
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       return FALSE;
 | |
|   }
 | |
| 
 | |
|   if (BnKey == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   *BnSize = Size;
 | |
|   Size    = BN_num_bytes (BnKey);
 | |
| 
 | |
|   if (*BnSize < Size) {
 | |
|     *BnSize = Size;
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if (BigNumber == NULL) {
 | |
|     *BnSize = Size;
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   *BnSize = BN_bn2bin (BnKey, BigNumber);
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Generates RSA key components.
 | |
| 
 | |
|   This function generates RSA key components. It takes RSA public exponent E and
 | |
|   length in bits of RSA modulus N as input, and generates all key components.
 | |
|   If PublicExponent is NULL, the default RSA public exponent (0x10001) will be used.
 | |
| 
 | |
|   Before this function can be invoked, pseudorandom number generator must be correctly
 | |
|   initialized by RandomSeed().
 | |
| 
 | |
|   If RsaContext is NULL, then return FALSE.
 | |
| 
 | |
|   @param[in, out]  RsaContext           Pointer to RSA context being set.
 | |
|   @param[in]       ModulusLength        Length of RSA modulus N in bits.
 | |
|   @param[in]       PublicExponent       Pointer to RSA public exponent.
 | |
|   @param[in]       PublicExponentSize   Size of RSA public exponent buffer in bytes.
 | |
| 
 | |
|   @retval  TRUE   RSA key component was generated successfully.
 | |
|   @retval  FALSE  Invalid RSA key component tag.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| RsaGenerateKey (
 | |
|   IN OUT  VOID         *RsaContext,
 | |
|   IN      UINTN        ModulusLength,
 | |
|   IN      CONST UINT8  *PublicExponent,
 | |
|   IN      UINTN        PublicExponentSize
 | |
|   )
 | |
| {
 | |
|   BIGNUM   *KeyE;
 | |
|   BOOLEAN  RetVal;
 | |
| 
 | |
|   //
 | |
|   // Check input parameters.
 | |
|   //
 | |
|   if ((RsaContext == NULL) || (ModulusLength > INT_MAX) || (PublicExponentSize > INT_MAX)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   KeyE = BN_new ();
 | |
|   if (KeyE == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   RetVal = FALSE;
 | |
| 
 | |
|   if (PublicExponent == NULL) {
 | |
|     if (BN_set_word (KeyE, 0x10001) == 0) {
 | |
|       goto _Exit;
 | |
|     }
 | |
|   } else {
 | |
|     if (BN_bin2bn (PublicExponent, (UINT32)PublicExponentSize, KeyE) == NULL) {
 | |
|       goto _Exit;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (RSA_generate_key_ex ((RSA *)RsaContext, (UINT32)ModulusLength, KeyE, NULL) == 1) {
 | |
|     RetVal = TRUE;
 | |
|   }
 | |
| 
 | |
| _Exit:
 | |
|   BN_free (KeyE);
 | |
|   return RetVal;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Validates key components of RSA context.
 | |
|   NOTE: This function performs integrity checks on all the RSA key material, so
 | |
|         the RSA key structure must contain all the private key data.
 | |
| 
 | |
|   This function validates key components of RSA context in following aspects:
 | |
|   - Whether p is a prime
 | |
|   - Whether q is a prime
 | |
|   - Whether n = p * q
 | |
|   - Whether d*e = 1  mod lcm(p-1,q-1)
 | |
| 
 | |
|   If RsaContext is NULL, then return FALSE.
 | |
| 
 | |
|   @param[in]  RsaContext  Pointer to RSA context to check.
 | |
| 
 | |
|   @retval  TRUE   RSA key components are valid.
 | |
|   @retval  FALSE  RSA key components are not valid.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| RsaCheckKey (
 | |
|   IN  VOID  *RsaContext
 | |
|   )
 | |
| {
 | |
|   UINTN  Reason;
 | |
| 
 | |
|   //
 | |
|   // Check input parameters.
 | |
|   //
 | |
|   if (RsaContext == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if (RSA_check_key ((RSA *)RsaContext) != 1) {
 | |
|     Reason = ERR_GET_REASON (ERR_peek_last_error ());
 | |
|     if ((Reason == RSA_R_P_NOT_PRIME) ||
 | |
|         (Reason == RSA_R_Q_NOT_PRIME) ||
 | |
|         (Reason == RSA_R_N_DOES_NOT_EQUAL_P_Q) ||
 | |
|         (Reason == RSA_R_D_E_NOT_CONGRUENT_TO_1))
 | |
|     {
 | |
|       return FALSE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme.
 | |
| 
 | |
|   This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme defined in
 | |
|   RSA PKCS#1.
 | |
|   If the Signature buffer is too small to hold the contents of signature, FALSE
 | |
|   is returned and SigSize is set to the required buffer size to obtain the signature.
 | |
| 
 | |
|   If RsaContext is NULL, then return FALSE.
 | |
|   If MessageHash is NULL, then return FALSE.
 | |
|   If HashSize is not equal to the size of MD5, SHA-1, SHA-256, SHA-384 or SHA-512 digest, then return FALSE.
 | |
|   If SigSize is large enough but Signature is NULL, then return FALSE.
 | |
| 
 | |
|   @param[in]       RsaContext   Pointer to RSA context for signature generation.
 | |
|   @param[in]       MessageHash  Pointer to octet message hash to be signed.
 | |
|   @param[in]       HashSize     Size of the message hash in bytes.
 | |
|   @param[out]      Signature    Pointer to buffer to receive RSA PKCS1-v1_5 signature.
 | |
|   @param[in, out]  SigSize      On input, the size of Signature buffer in bytes.
 | |
|                                 On output, the size of data returned in Signature buffer in bytes.
 | |
| 
 | |
|   @retval  TRUE   Signature successfully generated in PKCS1-v1_5.
 | |
|   @retval  FALSE  Signature generation failed.
 | |
|   @retval  FALSE  SigSize is too small.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| RsaPkcs1Sign (
 | |
|   IN      VOID         *RsaContext,
 | |
|   IN      CONST UINT8  *MessageHash,
 | |
|   IN      UINTN        HashSize,
 | |
|   OUT     UINT8        *Signature,
 | |
|   IN OUT  UINTN        *SigSize
 | |
|   )
 | |
| {
 | |
|   RSA    *Rsa;
 | |
|   UINTN  Size;
 | |
|   INT32  DigestType;
 | |
| 
 | |
|   //
 | |
|   // Check input parameters.
 | |
|   //
 | |
|   if ((RsaContext == NULL) || (MessageHash == NULL)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   Rsa  = (RSA *)RsaContext;
 | |
|   Size = RSA_size (Rsa);
 | |
| 
 | |
|   if (*SigSize < Size) {
 | |
|     *SigSize = Size;
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if (Signature == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Determine the message digest algorithm according to digest size.
 | |
|   //   Only MD5, SHA-1, SHA-256, SHA-384 or SHA-512 algorithm is supported.
 | |
|   //
 | |
|   switch (HashSize) {
 | |
|     case MD5_DIGEST_SIZE:
 | |
|       DigestType = NID_md5;
 | |
|       break;
 | |
| 
 | |
|     case SHA1_DIGEST_SIZE:
 | |
|       DigestType = NID_sha1;
 | |
|       break;
 | |
| 
 | |
|     case SHA256_DIGEST_SIZE:
 | |
|       DigestType = NID_sha256;
 | |
|       break;
 | |
| 
 | |
|     case SHA384_DIGEST_SIZE:
 | |
|       DigestType = NID_sha384;
 | |
|       break;
 | |
| 
 | |
|     case SHA512_DIGEST_SIZE:
 | |
|       DigestType = NID_sha512;
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       return FALSE;
 | |
|   }
 | |
| 
 | |
|   return (BOOLEAN)RSA_sign (
 | |
|                     DigestType,
 | |
|                     MessageHash,
 | |
|                     (UINT32)HashSize,
 | |
|                     Signature,
 | |
|                     (UINT32 *)SigSize,
 | |
|                     (RSA *)RsaContext
 | |
|                     );
 | |
| }
 |