git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11263 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1017 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1017 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Common interfaces to call Security library.
 | 
						|
 | 
						|
  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
 | 
						|
 | 
						|
  This program and the accompanying materials
 | 
						|
  are licensed and made available under the terms and conditions of the BSD License
 | 
						|
  which accompanies this distribution.  The full text of the license may be found at
 | 
						|
  http://opensource.org/licenses/bsd-license.php.
 | 
						|
 | 
						|
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "IpSecCryptIo.h"
 | 
						|
//
 | 
						|
// The informations for the supported Encrypt/Decrpt Alogrithm.
 | 
						|
//
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED ENCRYPT_ALGORITHM mIpsecEncryptAlgorithmList[IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE] = {
 | 
						|
  {IKE_EALG_NULL, 0, 0, 1, NULL, NULL, NULL, NULL},
 | 
						|
  {IKE_EALG_NONE, 0, 0, 1, NULL, NULL, NULL, NULL},  
 | 
						|
  {IKE_EALG_3DESCBC, 24, 8, 8, TdesGetContextSize, TdesInit, TdesCbcEncrypt, TdesCbcDecrypt},
 | 
						|
  {IKE_EALG_AESCBC, 16, 16, 16, AesGetContextSize, AesInit, AesCbcEncrypt, AesCbcDecrypt}
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// The informations for the supported Authentication algorithm
 | 
						|
//
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED AUTH_ALGORITHM mIpsecAuthAlgorithmList[IPSEC_AUTH_ALGORITHM_LIST_SIZE] = {
 | 
						|
  {IKE_AALG_NONE, 0, 0, 0, NULL, NULL, NULL, NULL},
 | 
						|
  {IKE_AALG_NULL, 0, 0, 0, NULL, NULL, NULL, NULL},
 | 
						|
  {IKE_AALG_SHA1HMAC, 20, 12, 64, HmacSha1GetContextSize, HmacSha1Init, HmacSha1Update, HmacSha1Final}
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// The information for the supported Hash aglorithm
 | 
						|
//
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED HASH_ALGORITHM mIpsecHashAlgorithmList[IPSEC_HASH_ALGORITHM_LIST_SIZE] = {
 | 
						|
  {IKE_AALG_NONE, 0, 0, 0, NULL, NULL, NULL, NULL},
 | 
						|
  {IKE_AALG_NULL, 0, 0, 0, NULL, NULL, NULL, NULL},
 | 
						|
  {IKE_AALG_SHA1HMAC, 20, 12, 64, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final}
 | 
						|
};
 | 
						|
 | 
						|
BOOLEAN  mInitialRandomSeed = FALSE;
 | 
						|
 | 
						|
/**
 | 
						|
  Get the block size of specified encryption alogrithm.
 | 
						|
 | 
						|
  @param[in]  AlgorithmId          The encryption algorithm ID.
 | 
						|
 | 
						|
  @return The value of block size.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
IpSecGetEncryptBlockSize (
 | 
						|
  IN UINT8   AlgorithmId
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8 Index;
 | 
						|
 | 
						|
  for (Index = 0; Index < IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE; Index++) {
 | 
						|
    if (AlgorithmId == mIpsecEncryptAlgorithmList[Index].AlgorithmId) {
 | 
						|
      return mIpsecEncryptAlgorithmList[Index].BlockSize;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return (UINTN) -1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the key length of the specified encryption alogrithm.
 | 
						|
 | 
						|
  @param[in]  AlgorithmId          The encryption algorithm ID.
 | 
						|
 | 
						|
  @return The value of key length.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
IpSecGetEncryptKeyLength (
 | 
						|
  IN UINT8   AlgorithmId
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8 Index;
 | 
						|
 | 
						|
  for (Index = 0; Index < IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE; Index++) {
 | 
						|
    if (AlgorithmId == mIpsecEncryptAlgorithmList[Index].AlgorithmId) {
 | 
						|
      return mIpsecEncryptAlgorithmList[Index].KeyLength;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return (UINTN) -1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the IV size of the specified encryption alogrithm.
 | 
						|
 | 
						|
  @param[in]  AlgorithmId          The encryption algorithm ID.
 | 
						|
 | 
						|
  @return The value of IV size.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
IpSecGetEncryptIvLength (
 | 
						|
  IN UINT8 AlgorithmId
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8 Index;
 | 
						|
 | 
						|
  for (Index = 0; Index < IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE; Index++) {
 | 
						|
    if (AlgorithmId == mIpsecEncryptAlgorithmList[Index].AlgorithmId) {
 | 
						|
      return mIpsecEncryptAlgorithmList[Index].IvLength;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return (UINTN) -1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the HMAC digest length by the specified Algorithm ID.
 | 
						|
 | 
						|
  @param[in]  AlgorithmId  The specified Alogrithm ID.
 | 
						|
 | 
						|
  @return The digest length of the specified Authentication Algorithm ID.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
IpSecGetHmacDigestLength (
 | 
						|
  IN UINT8  AlgorithmId
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8 Index;
 | 
						|
 | 
						|
  for (Index = 0; Index < IPSEC_AUTH_ALGORITHM_LIST_SIZE; Index++) {
 | 
						|
    if (mIpsecAuthAlgorithmList[Index].AlgorithmId == AlgorithmId) {
 | 
						|
      //
 | 
						|
      // Return the Digest Length of the Algorithm.
 | 
						|
      //
 | 
						|
      return mIpsecAuthAlgorithmList[Index].DigestLength;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the ICV size of the specified Authenticaion alogrithm.
 | 
						|
 | 
						|
  @param[in]  AlgorithmId          The Authentication algorithm ID.
 | 
						|
 | 
						|
  @return The value of ICV size.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
IpSecGetIcvLength (
 | 
						|
  IN UINT8  AlgorithmId
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8 Index;
 | 
						|
 | 
						|
  for (Index = 0; Index < IPSEC_AUTH_ALGORITHM_LIST_SIZE; Index++) {
 | 
						|
    if (AlgorithmId == mIpsecAuthAlgorithmList[Index].AlgorithmId) {
 | 
						|
      return mIpsecAuthAlgorithmList[Index].IcvLength;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return (UINTN) -1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Generate a random data for IV. If the IvSize is zero, not needed to create
 | 
						|
  IV and return EFI_SUCCESS.
 | 
						|
 | 
						|
  @param[in]  IvBuffer  The pointer of the IV buffer.
 | 
						|
  @param[in]  IvSize    The IV size in bytes.
 | 
						|
 | 
						|
  @retval     EFI_SUCCESS  Create a random data for IV.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecGenerateIv (
 | 
						|
  IN UINT8                           *IvBuffer,
 | 
						|
  IN UINTN                           IvSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (IvSize != 0) {
 | 
						|
    return IpSecCryptoIoGenerateRandomBytes (IvBuffer, IvSize);
 | 
						|
  }
 | 
						|
  
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get index of the specified encryption alogrithm from the mIpsecEncryptAlgorithemList.
 | 
						|
 | 
						|
  @param[in]  AlgorithmId          The encryption algorithm ID.
 | 
						|
 | 
						|
  @return the index.
 | 
						|
  
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
IpSecGetIndexFromEncList (
 | 
						|
  IN UINT8   AlgorithmId
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8 Index;
 | 
						|
  
 | 
						|
  for (Index = 0; Index < IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE; Index++) {
 | 
						|
    if (AlgorithmId == mIpsecEncryptAlgorithmList[Index].AlgorithmId) {
 | 
						|
      return Index;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  return (UINTN) -1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get index of the specified encryption alogrithm from the mIpsecAuthAlgorithemList.
 | 
						|
 | 
						|
  @param[in]  AlgorithmId          The encryption algorithm ID.
 | 
						|
 | 
						|
  @return the index.
 | 
						|
  
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
IpSecGetIndexFromAuthList (
 | 
						|
  IN UINT8   AlgorithmId
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8 Index;
 | 
						|
  
 | 
						|
  for (Index = 0; Index < IPSEC_AUTH_ALGORITHM_LIST_SIZE; Index++) {
 | 
						|
    if (AlgorithmId == mIpsecAuthAlgorithmList[Index].AlgorithmId) {
 | 
						|
      //
 | 
						|
      // The BlockSize is same with IvSize.
 | 
						|
      //
 | 
						|
      return Index;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  return (UINTN) -1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Encrypt the buffer.
 | 
						|
 | 
						|
  This function calls relevant encryption interface from CryptoLib according to
 | 
						|
  the input alogrithm ID. The InData should be multiple of block size. This function
 | 
						|
  doesn't perform the padding. If it has the Ivec data, the length of it should be
 | 
						|
  same with the block size. The block size is different from the different algorithm.
 | 
						|
 | 
						|
  @param[in]       AlgorithmId    The Alogrithem identification defined in RFC.
 | 
						|
  @param[in]       Key            Pointer to the buffer containing encrypting key.
 | 
						|
  @param[in]       KeyBits        The length of the key in bits.
 | 
						|
  @param[in]       Ivec           Point to the buffer containning the Initializeion
 | 
						|
                                  Vector (IV) data.
 | 
						|
  @param[in]       InData         Point to the buffer containing the data to be
 | 
						|
                                  encrypted.
 | 
						|
  @param[in]       InDataLength   The length of InData in Bytes.
 | 
						|
  @param[out]      OutData        Point to the buffer that receives the encryption
 | 
						|
                                  output.
 | 
						|
 | 
						|
  @retval EFI_UNSUPPORTED       The input Algorithm is not supported.
 | 
						|
  @retval EFI_OUT_OF_RESOURCE   The required resource can't be allocated.
 | 
						|
  @retval EFI_SUCCESS           The operation completed successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecCryptoIoEncrypt (
 | 
						|
  IN CONST UINT8      AlgorithmId,
 | 
						|
  IN CONST UINT8      *Key,
 | 
						|
  IN CONST UINTN      KeyBits,
 | 
						|
  IN CONST UINT8      *Ivec, OPTIONAL
 | 
						|
  IN       UINT8      *InData,
 | 
						|
  IN       UINTN      InDataLength,
 | 
						|
     OUT   UINT8      *OutData
 | 
						|
  )
 | 
						|
{  
 | 
						|
  UINTN         Index;
 | 
						|
  UINTN         ContextSize;
 | 
						|
  UINT8         *Context;
 | 
						|
  EFI_STATUS    Status;
 | 
						|
  
 | 
						|
  Status = EFI_UNSUPPORTED;
 | 
						|
  
 | 
						|
  switch (AlgorithmId) {
 | 
						|
 | 
						|
  case IKE_EALG_NULL:
 | 
						|
  case IKE_EALG_NONE:
 | 
						|
    CopyMem (OutData, InData, InDataLength);
 | 
						|
    return EFI_SUCCESS;
 | 
						|
 | 
						|
  case IKE_EALG_3DESCBC:
 | 
						|
  case IKE_EALG_AESCBC:
 | 
						|
    Index = IpSecGetIndexFromEncList (AlgorithmId);
 | 
						|
    if (Index == -1) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Get Context Size
 | 
						|
    //
 | 
						|
    ContextSize = mIpsecEncryptAlgorithmList[Index].CipherGetContextSize ();
 | 
						|
    Context     = AllocateZeroPool (ContextSize);
 | 
						|
 | 
						|
    if (Context == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Initiate Context
 | 
						|
    //
 | 
						|
    if (mIpsecEncryptAlgorithmList[Index].CipherInitiate (Context, Key, KeyBits)) {
 | 
						|
      if (mIpsecEncryptAlgorithmList[Index].CipherEncrypt (Context, InData, InDataLength, Ivec, OutData)) {
 | 
						|
        Status = EFI_SUCCESS;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    return Status;
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  if (Context != NULL) {
 | 
						|
    FreePool (Context);
 | 
						|
  }
 | 
						|
  
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Decrypts the buffer.
 | 
						|
 | 
						|
  This function calls relevant Decryption interface from CryptoLib according to
 | 
						|
  the input alogrithm ID. The InData should be multiple of block size. This function
 | 
						|
  doesn't perform the padding. If it has the Ivec data, the length of it should be
 | 
						|
  same with the block size. The block size is different from the different algorithm.
 | 
						|
 | 
						|
  @param[in]       AlgorithmId    The Alogrithem identification defined in RFC.
 | 
						|
  @param[in]       Key            Pointer to the buffer containing encrypting key.
 | 
						|
  @param[in]       KeyBits        The length of the key in bits.
 | 
						|
  @param[in]       Ivec           Point to the buffer containning the Initializeion
 | 
						|
                                  Vector (IV) data.
 | 
						|
  @param[in]       InData         Point to the buffer containing the data to be
 | 
						|
                                  decrypted.
 | 
						|
  @param[in]       InDataLength   The length of InData in Bytes.
 | 
						|
  @param[out]      OutData        Pointer to the buffer that receives the decryption
 | 
						|
                                  output.
 | 
						|
 | 
						|
  @retval EFI_UNSUPPORTED       The input Algorithm is not supported.
 | 
						|
  @retval EFI_OUT_OF_RESOURCE   The required resource can't be allocated.
 | 
						|
  @retval EFI_SUCCESS           The operation completed successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecCryptoIoDecrypt (
 | 
						|
  IN CONST UINT8      AlgorithmId,
 | 
						|
  IN CONST UINT8      *Key,
 | 
						|
  IN CONST UINTN      KeyBits,
 | 
						|
  IN CONST UINT8      *Ivec, OPTIONAL
 | 
						|
  IN       UINT8      *InData,
 | 
						|
  IN       UINTN      InDataLength,
 | 
						|
     OUT   UINT8      *OutData
 | 
						|
  )
 | 
						|
{  
 | 
						|
  UINTN         Index;
 | 
						|
  UINTN         ContextSize;
 | 
						|
  UINT8         *Context;
 | 
						|
  EFI_STATUS    Status;
 | 
						|
 | 
						|
  Status = EFI_UNSUPPORTED;
 | 
						|
 | 
						|
  switch (AlgorithmId) {
 | 
						|
 | 
						|
  case IKE_EALG_NULL:
 | 
						|
  case IKE_EALG_NONE:
 | 
						|
    CopyMem (OutData, InData, InDataLength);
 | 
						|
    return EFI_SUCCESS;
 | 
						|
 | 
						|
  case IKE_EALG_3DESCBC:
 | 
						|
  case IKE_EALG_AESCBC:
 | 
						|
    Index = IpSecGetIndexFromEncList(AlgorithmId);
 | 
						|
    if (Index == -1) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Get Context Size
 | 
						|
    //
 | 
						|
    ContextSize = mIpsecEncryptAlgorithmList[Index].CipherGetContextSize();
 | 
						|
    Context     = AllocateZeroPool (ContextSize);
 | 
						|
    if (Context == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Initiate Context
 | 
						|
    //
 | 
						|
    if (mIpsecEncryptAlgorithmList[Index].CipherInitiate (Context, Key, KeyBits)) {
 | 
						|
      if (mIpsecEncryptAlgorithmList[Index].CipherDecrypt (Context, InData, InDataLength, Ivec, OutData)) {
 | 
						|
        Status = EFI_SUCCESS;      
 | 
						|
      }
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Context != NULL) {
 | 
						|
    FreePool (Context);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Digests the Payload with key and store the result into the OutData.
 | 
						|
 | 
						|
  This function calls relevant Hmac interface from CryptoLib according to
 | 
						|
  the input alogrithm ID. It computes all datas from InDataFragment and output
 | 
						|
  the result into the OutData buffer. If the OutDataSize is larger than the related
 | 
						|
  HMAC alogrithm output size, return EFI_INVALID_PARAMETER.
 | 
						|
  
 | 
						|
  @param[in]      AlgorithmId     The authentication Identification.
 | 
						|
  @param[in]      Key             Pointer of the authentication key.
 | 
						|
  @param[in]      KeyLength       The length of the Key in bytes.
 | 
						|
  @param[in]      InDataFragment  The list contains all data to be authenticated.
 | 
						|
  @param[in]      FragmentCount   The size of the InDataFragment.
 | 
						|
  @param[out]     OutData         For in, the buffer to receive the output data.
 | 
						|
                                  For out, the buffer contains the authenticated data.
 | 
						|
  @param[in]      OutDataSize     The size of the buffer of OutData.
 | 
						|
 | 
						|
  @retval EFI_UNSUPPORTED       If the AuthAlg is not in the support list.
 | 
						|
  @retval EFI_INVALID_PARAMETER The OutData buffer size is larger than algorithm digest size.
 | 
						|
  @retval EFI_SUCCESS           Authenticate the payload successfully.
 | 
						|
  @retval otherwise             Authentication of the payload fails.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecCryptoIoHmac (
 | 
						|
  IN     CONST UINT8              AlgorithmId,
 | 
						|
  IN     CONST UINT8              *Key,
 | 
						|
  IN           UINTN              KeyLength,
 | 
						|
  IN           HASH_DATA_FRAGMENT *InDataFragment,
 | 
						|
  IN           UINTN              FragmentCount,
 | 
						|
     OUT       UINT8              *OutData,
 | 
						|
  IN           UINTN              OutDataSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN        ContextSize;
 | 
						|
  UINTN        Index;
 | 
						|
  UINT8        FragmentIndex;
 | 
						|
  UINT8        *HashContext;
 | 
						|
  EFI_STATUS   Status;
 | 
						|
  UINT8        *OutHashData;
 | 
						|
  UINTN        OutHashSize;
 | 
						|
 | 
						|
  Status      = EFI_UNSUPPORTED;
 | 
						|
  OutHashData = NULL;
 | 
						|
 | 
						|
  OutHashSize = IpSecGetHmacDigestLength (AlgorithmId);
 | 
						|
  //
 | 
						|
  // If the expected hash data size is larger than the related Hash algorithm
 | 
						|
  // output length, return EFI_INVALID_PARAMETER.
 | 
						|
  //
 | 
						|
  if (OutDataSize > OutHashSize) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  OutHashData = AllocatePool (OutHashSize);
 | 
						|
 | 
						|
  if (OutHashData == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  switch (AlgorithmId) {
 | 
						|
 | 
						|
  case IKE_AALG_NONE :
 | 
						|
  case IKE_AALG_NULL :
 | 
						|
    return EFI_SUCCESS;
 | 
						|
 | 
						|
  case IKE_AALG_SHA1HMAC:
 | 
						|
    Index = IpSecGetIndexFromAuthList (AlgorithmId);
 | 
						|
    if (Index == -1) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Get Context Size
 | 
						|
    //
 | 
						|
    ContextSize = mIpsecAuthAlgorithmList[Index].HmacGetContextSize();
 | 
						|
    HashContext = AllocateZeroPool (ContextSize);
 | 
						|
 | 
						|
    if (HashContext == NULL) {
 | 
						|
      Status = EFI_OUT_OF_RESOURCES;
 | 
						|
      goto Exit;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Initiate HMAC context and hash the input data.
 | 
						|
    //
 | 
						|
    if (mIpsecAuthAlgorithmList[Index].HmacInitiate(HashContext, Key, KeyLength)) {
 | 
						|
      for (FragmentIndex = 0; FragmentIndex < FragmentCount; FragmentIndex++) {
 | 
						|
        if (!mIpsecAuthAlgorithmList[Index].HmacUpdate (
 | 
						|
                HashContext,
 | 
						|
                InDataFragment[FragmentIndex].Data,
 | 
						|
                InDataFragment[FragmentIndex].DataSize
 | 
						|
                )
 | 
						|
          ) {
 | 
						|
          goto Exit;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (mIpsecAuthAlgorithmList[Index].HmacFinal (HashContext, OutHashData)) {
 | 
						|
        //
 | 
						|
        // In some cases, like the Icv computing, the Icv size might be less than
 | 
						|
        // the key length size, so copy the part of hash data to the OutData.
 | 
						|
        //
 | 
						|
        CopyMem (OutData, OutHashData, OutDataSize);
 | 
						|
        Status = EFI_SUCCESS;
 | 
						|
      }
 | 
						|
 | 
						|
      goto Exit;
 | 
						|
    }    
 | 
						|
      
 | 
						|
  default:
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
Exit:
 | 
						|
  if (HashContext != NULL) {
 | 
						|
    FreePool (HashContext);
 | 
						|
  }
 | 
						|
  if (OutHashData != NULL) {
 | 
						|
    FreePool (OutHashData);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Digests the Payload and store the result into the OutData.
 | 
						|
 | 
						|
  This function calls relevant Hash interface from CryptoLib according to
 | 
						|
  the input alogrithm ID. It computes all datas from InDataFragment and output
 | 
						|
  the result into the OutData buffer. If the OutDataSize is larger than the related
 | 
						|
  Hash alogrithm output size, return EFI_INVALID_PARAMETER.
 | 
						|
 | 
						|
  @param[in]      AlgorithmId     The authentication Identification.
 | 
						|
  @param[in]      InDataFragment  A list contains all data to be authenticated.
 | 
						|
  @param[in]      FragmentCount   The size of the InDataFragment.
 | 
						|
  @param[out]     OutData         For in, the buffer to receive the output data.
 | 
						|
                                  For out, the buffer contains the authenticated data.
 | 
						|
  @param[in]      OutDataSize     The size of the buffer of OutData.
 | 
						|
 | 
						|
  @retval EFI_UNSUPPORTED       If the AuthAlg is not in the support list.
 | 
						|
  @retval EFI_SUCCESS           Authenticated the payload successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER If the OutDataSize is larger than the related Hash
 | 
						|
                                algorithm could handle.
 | 
						|
  @retval otherwise             Authentication of the payload failed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecCryptoIoHash (
 | 
						|
  IN     CONST UINT8              AlgorithmId,
 | 
						|
  IN           HASH_DATA_FRAGMENT *InDataFragment,
 | 
						|
  IN           UINTN              FragmentCount,
 | 
						|
     OUT       UINT8              *OutData,
 | 
						|
  IN           UINTN              OutDataSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN        ContextSize;
 | 
						|
  UINTN        Index;
 | 
						|
  UINT8        FragmentIndex;
 | 
						|
  UINT8        *HashContext;
 | 
						|
  EFI_STATUS   Status;
 | 
						|
  UINT8        *OutHashData;
 | 
						|
  UINTN        OutHashSize;
 | 
						|
 | 
						|
  Status      = EFI_UNSUPPORTED;
 | 
						|
  OutHashData = NULL;
 | 
						|
  
 | 
						|
  OutHashSize = IpSecGetHmacDigestLength (AlgorithmId);
 | 
						|
  //
 | 
						|
  // If the expected hash data size is larger than the related Hash algorithm
 | 
						|
  // output length, return EFI_INVALID_PARAMETER.  
 | 
						|
  //
 | 
						|
  if (OutDataSize > OutHashSize) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  OutHashData = AllocatePool (OutHashSize);
 | 
						|
  if (OutHashData == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  
 | 
						|
  switch (AlgorithmId) {
 | 
						|
 | 
						|
  case IKE_AALG_NONE:
 | 
						|
  case IKE_AALG_NULL:
 | 
						|
    return EFI_SUCCESS;
 | 
						|
 | 
						|
  case IKE_AALG_SHA1HMAC:
 | 
						|
    Index = IpSecGetIndexFromAuthList (AlgorithmId);
 | 
						|
    if (Index == -1) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Get Context Size
 | 
						|
    //
 | 
						|
    ContextSize = mIpsecHashAlgorithmList[Index].HashGetContextSize();
 | 
						|
    HashContext = AllocateZeroPool (ContextSize);
 | 
						|
    if (HashContext == NULL) {
 | 
						|
      Status = EFI_OUT_OF_RESOURCES;
 | 
						|
      goto Exit;
 | 
						|
    }
 | 
						|
    
 | 
						|
    //
 | 
						|
    // Initiate Hash context and hash the input data.
 | 
						|
    //
 | 
						|
    if (mIpsecHashAlgorithmList[Index].HashInitiate(HashContext)) {
 | 
						|
      for (FragmentIndex = 0; FragmentIndex < FragmentCount; FragmentIndex++) {
 | 
						|
        if (!mIpsecHashAlgorithmList[Index].HashUpdate (
 | 
						|
                HashContext,
 | 
						|
                InDataFragment[FragmentIndex].Data,
 | 
						|
                InDataFragment[FragmentIndex].DataSize
 | 
						|
                )
 | 
						|
          ) {
 | 
						|
          goto Exit;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (mIpsecHashAlgorithmList[Index].HashFinal (HashContext, OutHashData)) {
 | 
						|
        //
 | 
						|
        // In some cases, like the Icv computing, the Icv size might be less than
 | 
						|
        // the key length size, so copy the part of hash data to the OutData.
 | 
						|
        //
 | 
						|
        CopyMem (OutData, OutHashData, OutDataSize);            
 | 
						|
        Status = EFI_SUCCESS;
 | 
						|
      }
 | 
						|
      
 | 
						|
      goto Exit;        
 | 
						|
    }    
 | 
						|
    
 | 
						|
  default:
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
Exit:
 | 
						|
  if (HashContext != NULL) {
 | 
						|
    FreePool (HashContext);
 | 
						|
  }
 | 
						|
  if (OutHashData != NULL) {
 | 
						|
    FreePool (OutHashData);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Generates the Diffie-Hellman public key.
 | 
						|
 | 
						|
  This function first initiate a DHContext, then call the DhSetParameter() to set
 | 
						|
  the prime and primelenght, at end call the DhGenerateKey() to generates random
 | 
						|
  secret exponent, and computes the public key. The output returned via parameter
 | 
						|
  PublicKey and PublicKeySize. DH context is updated accordingly. If the PublicKey
 | 
						|
  buffer is too small to hold the public key, EFI_INVALID_PARAMETER is returned
 | 
						|
  and PublicKeySize is set to the required buffer size to obtain the public key.
 | 
						|
 | 
						|
  @param[in, out] DhContext       Pointer to the DH context.
 | 
						|
  @param[in]      Generator       Vlaue of generator.
 | 
						|
  @param[in]      PrimeLength     Length in bits of prime to be generated.
 | 
						|
  @param[in]      Prime           Pointer to the buffer to receive the generated
 | 
						|
                                  prime number.
 | 
						|
  @param[out]     PublicKey       Pointer to the buffer to receive generated public key.
 | 
						|
  @param[in, out] PublicKeySize   For in, the size of PublicKey buffer in bytes.
 | 
						|
                                  For out, the size of data returned in PublicKey
 | 
						|
                                  buffer in bytes.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The operation perfoms successfully.
 | 
						|
  @retval Otherwise               The operation is failed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecCryptoIoDhGetPublicKey (
 | 
						|
  IN OUT   UINT8  **DhContext,
 | 
						|
  IN       UINTN  Generator,
 | 
						|
  IN       UINTN  PrimeLength,
 | 
						|
  IN CONST UINT8  *Prime,
 | 
						|
     OUT   UINT8  *PublicKey,
 | 
						|
  IN OUT   UINTN  *PublicKeySize
 | 
						|
  ) 
 | 
						|
{
 | 
						|
  EFI_STATUS   Status;
 | 
						|
  
 | 
						|
  *DhContext = DhNew ();
 | 
						|
  ASSERT (*DhContext != NULL);
 | 
						|
  if (!DhSetParameter (*DhContext, Generator, PrimeLength, Prime)) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto Exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!DhGenerateKey (*DhContext, PublicKey, PublicKeySize)) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto Exit;
 | 
						|
  }
 | 
						|
  return EFI_SUCCESS;
 | 
						|
 | 
						|
Exit:
 | 
						|
  if (*DhContext != NULL) {
 | 
						|
    DhFree (*DhContext);
 | 
						|
    DhContext = NULL;
 | 
						|
  }
 | 
						|
  
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Generates exchanged common key.
 | 
						|
 | 
						|
  Given peer's public key, this function computes the exchanged common key, based
 | 
						|
  on its own context including value of prime modulus and random secret exponent.
 | 
						|
 | 
						|
  @param[in, out] DhContext         Pointer to the DH context.
 | 
						|
  @param[in]      PeerPublicKey     Pointer to the peer's Public Key.
 | 
						|
  @param[in]      PeerPublicKeySize Size of peer's public key in bytes.
 | 
						|
  @param[out]     Key               Pointer to the buffer to receive generated key.
 | 
						|
  @param[in, out] KeySize           For in, the size of Key buffer in bytes.
 | 
						|
                                    For out, the size of data returned in Key
 | 
						|
                                    buffer in bytes.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The operation perfoms successfully.
 | 
						|
  @retval Otherwise                The operation is failed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecCryptoIoDhComputeKey (
 | 
						|
  IN   OUT   UINT8  *DhContext,     
 | 
						|
  IN   CONST UINT8  *PeerPublicKey,
 | 
						|
  IN         UINTN  PeerPublicKeySize,
 | 
						|
       OUT   UINT8  *Key,
 | 
						|
  IN   OUT   UINTN  *KeySize
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (!DhComputeKey (DhContext, PeerPublicKey, PeerPublicKeySize, Key, KeySize)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Releases the DH context. If DhContext is NULL, return EFI_INVALID_PARAMETER.
 | 
						|
 | 
						|
  @param[in, out]     DhContext         Pointer to the DH context to be freed.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The operation perfoms successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER    The DhContext is NULL.
 | 
						|
  
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecCryptoIoFreeDh (
 | 
						|
  IN   OUT   UINT8  **DhContext
 | 
						|
  )
 | 
						|
{ 
 | 
						|
  if (*DhContext == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  DhFree (*DhContext);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Generates random numbers of specified size.
 | 
						|
 | 
						|
  If the Random Generator wasn't initiated, initiate it first, then call RandomBytes.
 | 
						|
 | 
						|
  @param[out]  OutBuffer        Pointer to buffer to receive random value.
 | 
						|
  @param[in]   Bytes            Size of randome bytes to generate.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The operation perfoms successfully.
 | 
						|
  @retval Otherwise                The operation is failed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecCryptoIoGenerateRandomBytes (
 | 
						|
  OUT UINT8*    OutBuffer,
 | 
						|
  IN  UINTN     Bytes
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (!mInitialRandomSeed) {
 | 
						|
    RandomSeed (NULL, 0);
 | 
						|
    mInitialRandomSeed = TRUE;
 | 
						|
  }
 | 
						|
  if (RandomBytes (OutBuffer, Bytes)) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  } else {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Authenticate data with the certificate.
 | 
						|
 | 
						|
  @param[in]      InData          Pointer to the Data to be signed.
 | 
						|
  @param[in]      InDataSize      InData size in bytes.
 | 
						|
  @param[in]      PrivateKey      Pointer to the  private key.
 | 
						|
  @param[in]      PrivateKeySize  The size of Private Key in bytes.
 | 
						|
  @param[in]      KeyPassWord     Pointer to the password for retrieving private key.
 | 
						|
  @param[in]      KeyPwdSize      The size of Key Password in bytes.
 | 
						|
  @param[out]     OutData         The pointer to the signed data.
 | 
						|
  @param[in, out] OutDataSize     Pointer to contain the size of out data.
 | 
						|
 
 | 
						|
**/
 | 
						|
VOID
 | 
						|
IpSecCryptoIoAuthDataWithCertificate (
 | 
						|
  IN     UINT8   *InData,
 | 
						|
  IN     UINTN   InDataSize,
 | 
						|
  IN     UINT8   *PrivateKey,
 | 
						|
  IN     UINTN   PrivateKeySize,
 | 
						|
  IN     UINT8   *KeyPassWord,
 | 
						|
  IN     UINTN   KeyPwdSize,
 | 
						|
     OUT UINT8   **OutData,
 | 
						|
  IN OUT UINTN   *OutDataSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8         *RsaContext;
 | 
						|
  UINT8         *Signature;
 | 
						|
  UINTN         SigSize;
 | 
						|
   
 | 
						|
  SigSize   = 0;
 | 
						|
  //
 | 
						|
  // Retrieve RSA Private Key from password-protected PEM data
 | 
						|
  //
 | 
						|
  RsaGetPrivateKeyFromPem (
 | 
						|
    (CONST UINT8 *)PrivateKey,
 | 
						|
    PrivateKeySize,
 | 
						|
    (CONST CHAR8 *)KeyPassWord,
 | 
						|
    (VOID **) &RsaContext
 | 
						|
    );
 | 
						|
  if (RsaContext == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Sign data
 | 
						|
  //
 | 
						|
  Signature = NULL;  
 | 
						|
  if (!RsaPkcs1Sign (RsaContext, InData, InDataSize, Signature, &SigSize)) {
 | 
						|
    Signature = AllocateZeroPool (SigSize);
 | 
						|
  } else {
 | 
						|
    return;
 | 
						|
  } 
 | 
						|
 | 
						|
  RsaPkcs1Sign (RsaContext, InData, InDataSize, Signature, &SigSize);
 | 
						|
 | 
						|
  *OutData     = Signature;
 | 
						|
  *OutDataSize = SigSize;
 | 
						|
 | 
						|
  if (RsaContext != NULL) {
 | 
						|
    RsaFree (RsaContext);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Verify the singed data with the public key which is contained in a certificate.
 | 
						|
 | 
						|
  @param[in]     InCert          Pointer to the Certificate which contains the
 | 
						|
                                 public key.
 | 
						|
  @param[in]     CertLen         The size of Certificate in bytes.
 | 
						|
  @param[in]     InCa            Pointer to the CA certificate
 | 
						|
  @param[in]     CaLen           The size of CA certificate in bytes.
 | 
						|
  @param[in]     InData          Pointer to octect message hash to be checked.
 | 
						|
  @param[in]     InDataSize      Size of the message hash in bytes.
 | 
						|
  @param[in]     Singnature      The pointer to the RSA PKCS1-V1_5 signature to be verifed.
 | 
						|
  @param[in]     SigSize         Size of signature in bytes.
 | 
						|
 | 
						|
  @retval  TRUE   Valid signature encoded in PKCS1-v1_5.
 | 
						|
  @retval  FALSE  Invalid signature or invalid RSA context.
 | 
						|
 
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IpSecCryptoIoVerifySignDataByCertificate (
 | 
						|
  IN     UINT8   *InCert,
 | 
						|
  IN     UINTN   CertLen,
 | 
						|
  IN     UINT8   *InCa,
 | 
						|
  IN     UINTN   CaLen,
 | 
						|
  IN     UINT8   *InData,
 | 
						|
  IN     UINTN   InDataSize,
 | 
						|
  IN     UINT8   *Singnature,
 | 
						|
  IN     UINTN   SigSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8         *RsaContext;
 | 
						|
  BOOLEAN       Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Create the RSA Context
 | 
						|
  //
 | 
						|
  RsaContext = RsaNew ();
 | 
						|
  if (RsaContext == NULL) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Verify the validity of X509 Certificate
 | 
						|
  //
 | 
						|
  if (!X509VerifyCert (InCert, CertLen, InCa, CaLen)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Retrieve the RSA public Key from Certificate
 | 
						|
  //
 | 
						|
  RsaGetPublicKeyFromX509 ((CONST UINT8 *)InCert, CertLen, (VOID **)&RsaContext);
 | 
						|
 
 | 
						|
  //
 | 
						|
  // Verify data
 | 
						|
  //
 | 
						|
  Status = RsaPkcs1Verify (RsaContext, InData, InDataSize, Singnature, SigSize);
 | 
						|
 | 
						|
  if (RsaContext != NULL) {
 | 
						|
    RsaFree (RsaContext);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Retrieves the RSA Public Key from one X509 certificate (DER format only).
 | 
						|
 | 
						|
  @param[in]     InCert            Pointer to the certificate.
 | 
						|
  @param[in]     CertLen           The size of the certificate in bytes.
 | 
						|
  @param[out]    PublicKey         Pointer to the retrieved public key.
 | 
						|
  @param[out]    PublicKeyLen      Size of Public Key in bytes.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS            Successfully get the public Key.
 | 
						|
  @retval  EFI_INVALID_PARAMETER  The certificate is malformed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecCryptoIoGetPublicKeyFromCert (
 | 
						|
  IN     UINT8   *InCert,
 | 
						|
  IN     UINTN   CertLen,
 | 
						|
  OUT    UINT8   **PublicKey,
 | 
						|
  OUT    UINTN   *PublicKeyLen
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8         *RsaContext;
 | 
						|
  EFI_STATUS    Status;
 | 
						|
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
 | 
						|
  //
 | 
						|
  // Create the RSA Context
 | 
						|
  //
 | 
						|
  RsaContext = RsaNew ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Retrieve the RSA public key from CA Certificate
 | 
						|
  //
 | 
						|
  if (!RsaGetPublicKeyFromX509 ((CONST UINT8 *)InCert, CertLen, (VOID **) &RsaContext)) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
    goto EXIT;
 | 
						|
  }
 | 
						|
 | 
						|
  *PublicKeyLen = 0;
 | 
						|
 
 | 
						|
  RsaGetKey (RsaContext, RsaKeyN, NULL, PublicKeyLen);
 | 
						|
 
 | 
						|
  *PublicKey = AllocateZeroPool (*PublicKeyLen);
 | 
						|
  ASSERT (*PublicKey != NULL);
 | 
						|
 | 
						|
  if (!RsaGetKey (RsaContext, RsaKeyN, *PublicKey, PublicKeyLen)) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
EXIT:
 | 
						|
  if (RsaContext != NULL) {
 | 
						|
    RsaFree (RsaContext);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Retrieves the subject name from one X509 certificate (DER format only).
 | 
						|
 | 
						|
  @param[in]     InCert            Pointer to the X509 certificate.
 | 
						|
  @param[in]     CertSize          The size of the X509 certificate in bytes.
 | 
						|
  @param[out]    CertSubject       Pointer to the retrieved certificate subject.
 | 
						|
  @param[out]    SubjectSize       The size of Certificate Subject in bytes.
 | 
						|
  
 | 
						|
  @retval  EFI_SUCCESS            Retrieved the certificate subject successfully.
 | 
						|
  @retval  EFI_INVALID_PARAMETER  The certificate is malformed.
 | 
						|
 
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecCryptoIoGetSubjectFromCert (
 | 
						|
  IN     UINT8   *InCert,
 | 
						|
  IN     UINTN   CertSize,
 | 
						|
  OUT    UINT8   **CertSubject,
 | 
						|
  OUT    UINTN   *SubjectSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS    Status;
 | 
						|
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
 | 
						|
  *SubjectSize = 0;
 | 
						|
  X509GetSubjectName (InCert, CertSize, *CertSubject, SubjectSize);
 | 
						|
 | 
						|
  *CertSubject = AllocateZeroPool (*SubjectSize);
 | 
						|
  if (!X509GetSubjectName (InCert, CertSize, *CertSubject, SubjectSize)) {
 | 
						|
    Status = EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |