mirror of
				https://gitlab.com/qemu-project/edk2.git
				synced 2025-10-30 07:56:39 +08:00 
			
		
		
		
	 a074649c60
			
		
	
	a074649c60
	
	
	
		
			
			Fix the coverity warnings reported in the CryptoPkg. Signed-off-by: Kanagavel S <kanagavels@ami.com>
		
			
				
	
	
		
			1721 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1721 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   SSL/TLS Configuration Library Wrapper Implementation over OpenSSL.
 | |
| 
 | |
| Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
| (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "InternalTlsLib.h"
 | |
| 
 | |
| typedef struct {
 | |
|   //
 | |
|   // TLS Algorithm
 | |
|   //
 | |
|   UINT8          Algo;
 | |
|   //
 | |
|   // TLS Algorithm name
 | |
|   //
 | |
|   CONST CHAR8    *Name;
 | |
| } TLS_ALGO_TO_NAME;
 | |
| 
 | |
| STATIC CONST TLS_ALGO_TO_NAME  TlsHashAlgoToName[] = {
 | |
|   { TlsHashAlgoNone,   NULL     },
 | |
|   { TlsHashAlgoMd5,    "MD5"    },
 | |
|   { TlsHashAlgoSha1,   "SHA1"   },
 | |
|   { TlsHashAlgoSha224, "SHA224" },
 | |
|   { TlsHashAlgoSha256, "SHA256" },
 | |
|   { TlsHashAlgoSha384, "SHA384" },
 | |
|   { TlsHashAlgoSha512, "SHA512" },
 | |
| };
 | |
| 
 | |
| STATIC CONST TLS_ALGO_TO_NAME  TlsSignatureAlgoToName[] = {
 | |
|   { TlsSignatureAlgoAnonymous, NULL    },
 | |
|   { TlsSignatureAlgoRsa,       "RSA"   },
 | |
|   { TlsSignatureAlgoDsa,       "DSA"   },
 | |
|   { TlsSignatureAlgoEcdsa,     "ECDSA" },
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Set a new TLS/SSL method for a particular TLS object.
 | |
| 
 | |
|   This function sets a new TLS/SSL method for a particular TLS object.
 | |
| 
 | |
|   @param[in]  Tls         Pointer to a TLS object.
 | |
|   @param[in]  MajorVer    Major Version of TLS/SSL Protocol.
 | |
|   @param[in]  MinorVer    Minor Version of TLS/SSL Protocol.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           The TLS/SSL method was set successfully.
 | |
|   @retval  EFI_INVALID_PARAMETER The parameter is invalid.
 | |
|   @retval  EFI_UNSUPPORTED       Unsupported TLS/SSL method.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetVersion (
 | |
|   IN     VOID   *Tls,
 | |
|   IN     UINT8  MajorVer,
 | |
|   IN     UINT8  MinorVer
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
|   UINT16          ProtoVersion;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   ProtoVersion = (MajorVer << 8) | MinorVer;
 | |
| 
 | |
|   //
 | |
|   // Bound TLS method to the particular specified version.
 | |
|   //
 | |
|   switch (ProtoVersion) {
 | |
|     case TLS1_VERSION:
 | |
|       //
 | |
|       // TLS 1.0
 | |
|       //
 | |
|       SSL_set_min_proto_version (TlsConn->Ssl, TLS1_VERSION);
 | |
|       SSL_set_max_proto_version (TlsConn->Ssl, TLS1_VERSION);
 | |
|       break;
 | |
|     case TLS1_1_VERSION:
 | |
|       //
 | |
|       // TLS 1.1
 | |
|       //
 | |
|       SSL_set_min_proto_version (TlsConn->Ssl, TLS1_1_VERSION);
 | |
|       SSL_set_max_proto_version (TlsConn->Ssl, TLS1_1_VERSION);
 | |
|       break;
 | |
|     case TLS1_2_VERSION:
 | |
|       //
 | |
|       // TLS 1.2
 | |
|       //
 | |
|       SSL_set_min_proto_version (TlsConn->Ssl, TLS1_2_VERSION);
 | |
|       SSL_set_max_proto_version (TlsConn->Ssl, TLS1_2_VERSION);
 | |
|       break;
 | |
|     default:
 | |
|       //
 | |
|       // Unsupported Protocol Version
 | |
|       //
 | |
|       return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set TLS object to work in client or server mode.
 | |
| 
 | |
|   This function prepares a TLS object to work in client or server mode.
 | |
| 
 | |
|   @param[in]  Tls         Pointer to a TLS object.
 | |
|   @param[in]  IsServer    Work in server mode.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           The TLS/SSL work mode was set successfully.
 | |
|   @retval  EFI_INVALID_PARAMETER The parameter is invalid.
 | |
|   @retval  EFI_UNSUPPORTED       Unsupported TLS/SSL work mode.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetConnectionEnd (
 | |
|   IN     VOID     *Tls,
 | |
|   IN     BOOLEAN  IsServer
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (!IsServer) {
 | |
|     //
 | |
|     // Set TLS to work in Client mode.
 | |
|     //
 | |
|     SSL_set_connect_state (TlsConn->Ssl);
 | |
|   } else {
 | |
|     //
 | |
|     // Set TLS to work in Server mode.
 | |
|     // It is unsupported for UEFI version currently.
 | |
|     //
 | |
|     // SSL_set_accept_state (TlsConn->Ssl);
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set the ciphers list to be used by the TLS object.
 | |
| 
 | |
|   This function sets the ciphers for use by a specified TLS object.
 | |
| 
 | |
|   @param[in]  Tls          Pointer to a TLS object.
 | |
|   @param[in]  CipherId     Array of UINT16 cipher identifiers. Each UINT16
 | |
|                            cipher identifier comes from the TLS Cipher Suite
 | |
|                            Registry of the IANA, interpreting Byte1 and Byte2
 | |
|                            in network (big endian) byte order.
 | |
|   @param[in]  CipherNum    The number of cipher in the list.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           The ciphers list was set successfully.
 | |
|   @retval  EFI_INVALID_PARAMETER The parameter is invalid.
 | |
|   @retval  EFI_UNSUPPORTED       No supported TLS cipher was found in CipherId.
 | |
|   @retval  EFI_OUT_OF_RESOURCES  Memory allocation failed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetCipherList (
 | |
|   IN     VOID    *Tls,
 | |
|   IN     UINT16  *CipherId,
 | |
|   IN     UINTN   CipherNum
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION    *TlsConn;
 | |
|   EFI_STATUS        Status;
 | |
|   CONST SSL_CIPHER  **MappedCipher;
 | |
|   UINTN             MappedCipherBytes;
 | |
|   UINTN             MappedCipherCount;
 | |
|   UINTN             CipherStringSize;
 | |
|   UINTN             Index;
 | |
|   INT32             StackIdx;
 | |
|   CHAR8             *CipherString;
 | |
|   CHAR8             *CipherStringPosition;
 | |
| 
 | |
|   STACK_OF (SSL_CIPHER)      *OpensslCipherStack;
 | |
|   CONST SSL_CIPHER  *OpensslCipher;
 | |
|   CONST CHAR8       *OpensslCipherName;
 | |
|   UINTN             OpensslCipherNameLength;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (CipherId == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Allocate the MappedCipher array for recording the mappings that we find
 | |
|   // for the input IANA identifiers in CipherId.
 | |
|   //
 | |
|   Status = SafeUintnMult (
 | |
|              CipherNum,
 | |
|              sizeof (*MappedCipher),
 | |
|              &MappedCipherBytes
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   MappedCipher = AllocatePool (MappedCipherBytes);
 | |
|   if (MappedCipher == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   OpensslCipherStack = SSL_get_ciphers (TlsConn->Ssl);
 | |
| 
 | |
|   //
 | |
|   // Map the cipher IDs, and count the number of bytes for the full
 | |
|   // CipherString.
 | |
|   //
 | |
|   MappedCipherCount = 0;
 | |
|   CipherStringSize  = 0;
 | |
|   for (Index = 0; OpensslCipherStack != NULL && Index < CipherNum; Index++) {
 | |
|     //
 | |
|     // Look up the IANA-to-OpenSSL mapping.
 | |
|     //
 | |
|     for (StackIdx = 0; StackIdx < sk_SSL_CIPHER_num (OpensslCipherStack); StackIdx++) {
 | |
|       OpensslCipher = sk_SSL_CIPHER_value (OpensslCipherStack, StackIdx);
 | |
|       if (CipherId[Index] == SSL_CIPHER_get_protocol_id (OpensslCipher)) {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (StackIdx == sk_SSL_CIPHER_num (OpensslCipherStack)) {
 | |
|       DEBUG ((
 | |
|         DEBUG_VERBOSE,
 | |
|         "%a:%a: skipping CipherId=0x%04x\n",
 | |
|         gEfiCallerBaseName,
 | |
|         __func__,
 | |
|         CipherId[Index]
 | |
|         ));
 | |
|       //
 | |
|       // Skipping the cipher is valid because CipherId is an ordered
 | |
|       // preference list of ciphers, thus we can filter it as long as we
 | |
|       // don't change the relative order of elements on it.
 | |
|       //
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Accumulate cipher name string length into CipherStringSize. If this
 | |
|     // is not the first successful mapping, account for a colon (":") prefix
 | |
|     // too.
 | |
|     //
 | |
|     if (MappedCipherCount > 0) {
 | |
|       Status = SafeUintnAdd (CipherStringSize, 1, &CipherStringSize);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         Status = EFI_OUT_OF_RESOURCES;
 | |
|         goto FreeMappedCipher;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     Status = SafeUintnAdd (
 | |
|                CipherStringSize,
 | |
|                AsciiStrLen (SSL_CIPHER_get_name (OpensslCipher)),
 | |
|                &CipherStringSize
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto FreeMappedCipher;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Record the mapping.
 | |
|     //
 | |
|     MappedCipher[MappedCipherCount++] = OpensslCipher;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Verify that at least one IANA cipher ID could be mapped; account for the
 | |
|   // terminating NUL character in CipherStringSize; allocate CipherString.
 | |
|   //
 | |
|   if (MappedCipherCount == 0) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "%a:%a: no CipherId could be mapped\n",
 | |
|       gEfiCallerBaseName,
 | |
|       __func__
 | |
|       ));
 | |
|     Status = EFI_UNSUPPORTED;
 | |
|     goto FreeMappedCipher;
 | |
|   }
 | |
| 
 | |
|   Status = SafeUintnAdd (CipherStringSize, 1, &CipherStringSize);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto FreeMappedCipher;
 | |
|   }
 | |
| 
 | |
|   CipherString = AllocatePool (CipherStringSize);
 | |
|   if (CipherString == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto FreeMappedCipher;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Go over the collected mappings and populate CipherString.
 | |
|   //
 | |
|   CipherStringPosition = CipherString;
 | |
|   for (Index = 0; Index < MappedCipherCount; Index++) {
 | |
|     OpensslCipher           = MappedCipher[Index];
 | |
|     OpensslCipherName       = SSL_CIPHER_get_name (OpensslCipher);
 | |
|     OpensslCipherNameLength = AsciiStrLen (OpensslCipherName);
 | |
|     //
 | |
|     // Append the colon (":") prefix except for the first mapping, then append
 | |
|     // OpensslCipherName.
 | |
|     //
 | |
|     if (Index > 0) {
 | |
|       *(CipherStringPosition++) = ':';
 | |
|     }
 | |
| 
 | |
|     CopyMem (
 | |
|       CipherStringPosition,
 | |
|       OpensslCipherName,
 | |
|       OpensslCipherNameLength
 | |
|       );
 | |
|     CipherStringPosition += OpensslCipherNameLength;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // NUL-terminate CipherString.
 | |
|   //
 | |
|   *(CipherStringPosition++) = '\0';
 | |
|   ASSERT (CipherStringPosition == CipherString + CipherStringSize);
 | |
| 
 | |
|   //
 | |
|   // Log CipherString for debugging. CipherString can be very long if the
 | |
|   // caller provided a large CipherId array, so log CipherString in segments of
 | |
|   // 79 non-newline characters. (MAX_DEBUG_MESSAGE_LENGTH is usually 0x100 in
 | |
|   // DebugLib instances.)
 | |
|   //
 | |
|   DEBUG_CODE_BEGIN ();
 | |
|   UINTN  FullLength;
 | |
|   UINTN  SegmentLength;
 | |
| 
 | |
|   FullLength = CipherStringSize - 1;
 | |
|   DEBUG ((
 | |
|     DEBUG_VERBOSE,
 | |
|     "%a:%a: CipherString={\n",
 | |
|     gEfiCallerBaseName,
 | |
|     __func__
 | |
|     ));
 | |
|   for (CipherStringPosition = CipherString;
 | |
|        CipherStringPosition < CipherString + FullLength;
 | |
|        CipherStringPosition += SegmentLength)
 | |
|   {
 | |
|     SegmentLength = FullLength - (CipherStringPosition - CipherString);
 | |
|     if (SegmentLength > 79) {
 | |
|       SegmentLength = 79;
 | |
|     }
 | |
| 
 | |
|     DEBUG ((DEBUG_VERBOSE, "%.*a\n", SegmentLength, CipherStringPosition));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((DEBUG_VERBOSE, "}\n"));
 | |
|   //
 | |
|   // Restore the pre-debug value of CipherStringPosition by skipping over the
 | |
|   // trailing NUL.
 | |
|   //
 | |
|   CipherStringPosition++;
 | |
|   ASSERT (CipherStringPosition == CipherString + CipherStringSize);
 | |
|   DEBUG_CODE_END ();
 | |
| 
 | |
|   //
 | |
|   // Sets the ciphers for use by the Tls object.
 | |
|   //
 | |
|   if (SSL_set_cipher_list (TlsConn->Ssl, CipherString) <= 0) {
 | |
|     Status = EFI_UNSUPPORTED;
 | |
|     goto FreeCipherString;
 | |
|   }
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
| FreeCipherString:
 | |
|   FreePool (CipherString);
 | |
| 
 | |
| FreeMappedCipher:
 | |
|   FreePool ((VOID *)MappedCipher);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set the compression method for TLS/SSL operations.
 | |
| 
 | |
|   This function handles TLS/SSL integrated compression methods.
 | |
| 
 | |
|   @param[in]  CompMethod    The compression method ID.
 | |
| 
 | |
|   @retval  EFI_SUCCESS        The compression method for the communication was
 | |
|                               set successfully.
 | |
|   @retval  EFI_UNSUPPORTED    Unsupported compression method.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetCompressionMethod (
 | |
|   IN     UINT8  CompMethod
 | |
|   )
 | |
| {
 | |
|   COMP_METHOD  *Cm;
 | |
|   INTN         Ret;
 | |
| 
 | |
|   Cm  = NULL;
 | |
|   Ret = 0;
 | |
| 
 | |
|   if (CompMethod == 0) {
 | |
|     //
 | |
|     // TLS defines one standard compression method, CompressionMethod.null (0),
 | |
|     // which specifies that data exchanged via the record protocol will not be compressed.
 | |
|     // So, return EFI_SUCCESS directly (RFC 3749).
 | |
|     //
 | |
|     return EFI_SUCCESS;
 | |
|   } else if (CompMethod == 1) {
 | |
|     Cm = COMP_zlib ();
 | |
|   } else {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Adds the compression method to the list of available
 | |
|   // compression methods.
 | |
|   //
 | |
|   Ret = SSL_COMP_add_compression_method (CompMethod, Cm);
 | |
|   if (Ret != 0) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set peer certificate verification mode for the TLS connection.
 | |
| 
 | |
|   This function sets the verification mode flags for the TLS connection.
 | |
| 
 | |
|   @param[in]  Tls           Pointer to the TLS object.
 | |
|   @param[in]  VerifyMode    A set of logically or'ed verification mode flags.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| TlsSetVerify (
 | |
|   IN     VOID    *Tls,
 | |
|   IN     UINT32  VerifyMode
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL)) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Set peer certificate verification parameters with NULL callback.
 | |
|   //
 | |
|   SSL_set_verify (TlsConn->Ssl, VerifyMode, NULL);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set the specified host name to be verified.
 | |
| 
 | |
|   @param[in]  Tls           Pointer to the TLS object.
 | |
|   @param[in]  Flags         The setting flags during the validation.
 | |
|   @param[in]  HostName      The specified host name to be verified.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           The HostName setting was set successfully.
 | |
|   @retval  EFI_INVALID_PARAMETER The parameter is invalid.
 | |
|   @retval  EFI_ABORTED           Invalid HostName setting.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetVerifyHost (
 | |
|   IN     VOID    *Tls,
 | |
|   IN     UINT32  Flags,
 | |
|   IN     CHAR8   *HostName
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION     *TlsConn;
 | |
|   X509_VERIFY_PARAM  *VerifyParam;
 | |
|   UINTN              BinaryAddressSize;
 | |
|   UINT8              BinaryAddress[MAX (NS_INADDRSZ, NS_IN6ADDRSZ)];
 | |
|   INTN               ParamStatus;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (HostName == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   DEBUG ((
 | |
|     DEBUG_VERBOSE,
 | |
|     "%a:%a: SNI hostname: %a\n",
 | |
|     gEfiCallerBaseName,
 | |
|     __func__,
 | |
|     HostName
 | |
|     ));
 | |
| 
 | |
|   if (!SSL_set_tlsext_host_name (TlsConn->Ssl, HostName)) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "%a:%a: Could not set hostname %a for SNI\n",
 | |
|       gEfiCallerBaseName,
 | |
|       __func__,
 | |
|       HostName
 | |
|       ));
 | |
|   }
 | |
| 
 | |
|   SSL_set_hostflags (TlsConn->Ssl, Flags);
 | |
| 
 | |
|   VerifyParam = SSL_get0_param (TlsConn->Ssl);
 | |
|   ASSERT (VerifyParam != NULL);
 | |
| 
 | |
|   BinaryAddressSize = 0;
 | |
|   if (inet_pton (AF_INET6, HostName, BinaryAddress) == 1) {
 | |
|     BinaryAddressSize = NS_IN6ADDRSZ;
 | |
|   } else if (inet_pton (AF_INET, HostName, BinaryAddress) == 1) {
 | |
|     BinaryAddressSize = NS_INADDRSZ;
 | |
|   }
 | |
| 
 | |
|   if (BinaryAddressSize > 0) {
 | |
|     DEBUG ((
 | |
|       DEBUG_VERBOSE,
 | |
|       "%a:%a: parsed \"%a\" as an IPv%c address "
 | |
|       "literal\n",
 | |
|       gEfiCallerBaseName,
 | |
|       __func__,
 | |
|       HostName,
 | |
|       (UINTN)((BinaryAddressSize == NS_IN6ADDRSZ) ? '6' : '4')
 | |
|       ));
 | |
|     ParamStatus = X509_VERIFY_PARAM_set1_ip (
 | |
|                     VerifyParam,
 | |
|                     BinaryAddress,
 | |
|                     BinaryAddressSize
 | |
|                     );
 | |
|   } else {
 | |
|     ParamStatus = X509_VERIFY_PARAM_set1_host (VerifyParam, HostName, 0);
 | |
|   }
 | |
| 
 | |
|   return (ParamStatus == 1) ? EFI_SUCCESS : EFI_ABORTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Callback function to get the server name.
 | |
| 
 | |
|   @param[in]  SSL
 | |
|   @param[in]  INT32
 | |
|   @param[in]  Arg
 | |
| 
 | |
|   @retval  INT32
 | |
| **/
 | |
| STATIC
 | |
| INT32
 | |
| SslServerNameCallback (
 | |
|   SSL    *Ssl,
 | |
|   INT32  *Ad,
 | |
|   VOID   *Arg
 | |
|   )
 | |
| {
 | |
|   const CHAR8  *HostName = NULL;
 | |
|   TLS_EXT_CTX  *TlsCtx   = (TLS_EXT_CTX *)Arg;
 | |
| 
 | |
|   HostName = SSL_get_servername (Ssl, TLSEXT_NAMETYPE_host_name);
 | |
| 
 | |
|   if (SSL_get_servername_type (Ssl) != -1) {
 | |
|     TlsCtx->Ack = !SSL_session_reused (Ssl) && HostName != NULL;
 | |
|   }
 | |
| 
 | |
|   return SSL_TLSEXT_ERR_OK;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set the specified server name in Server/Client.
 | |
| 
 | |
|   @param[in]  Tls           Pointer to the TLS object.
 | |
|   @param[in]  SslCtx        Pointer to the SSL object.
 | |
|   @param[in]  HostName      The specified server name to be set.
 | |
| 
 | |
|   @retval  EFI_SUCCESS      The Server Name was set successfully.
 | |
|   @retval  EFI_UNSUPPORTED  Failed to set the Server Name.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetServerName (
 | |
|   VOID   *Tls,
 | |
|   VOID   *SslCtx,
 | |
|   CHAR8  *HostName
 | |
|   )
 | |
| {
 | |
|   SSL_CTX         *Ctx;
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
|   UINT32          RetVal;
 | |
|   TLS_EXT_CTX     *TlsExtCtx = NULL;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
|   Ctx     = (SSL_CTX *)SslCtx;
 | |
| 
 | |
|   if (TlsConn == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   TlsExtCtx = AllocateZeroPool (sizeof (TLS_EXT_CTX));
 | |
|   if (TlsExtCtx == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   RetVal = SSL_CTX_set_tlsext_servername_callback (Ctx, SslServerNameCallback);
 | |
|   if (!RetVal) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   RetVal = SSL_CTX_set_tlsext_servername_arg (Ctx, TlsExtCtx);
 | |
|   if (!RetVal) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   RetVal = SSL_set_tlsext_host_name (TlsConn->Ssl, HostName);
 | |
| 
 | |
|   if (!RetVal) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Sets a TLS/SSL session ID to be used during TLS/SSL connect.
 | |
| 
 | |
|   This function sets a session ID to be used when the TLS/SSL connection is
 | |
|   to be established.
 | |
| 
 | |
|   @param[in]  Tls             Pointer to the TLS object.
 | |
|   @param[in]  SessionId       Session ID data used for session resumption.
 | |
|   @param[in]  SessionIdLen    Length of Session ID in bytes.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           Session ID was set successfully.
 | |
|   @retval  EFI_INVALID_PARAMETER The parameter is invalid.
 | |
|   @retval  EFI_UNSUPPORTED       No available session for ID setting.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetSessionId (
 | |
|   IN     VOID    *Tls,
 | |
|   IN     UINT8   *SessionId,
 | |
|   IN     UINT16  SessionIdLen
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
|   SSL_SESSION     *Session;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
|   Session = NULL;
 | |
| 
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (SessionId == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Session = SSL_get_session (TlsConn->Ssl);
 | |
|   if (Session == NULL) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   SSL_SESSION_set1_id (Session, (const unsigned char *)SessionId, SessionIdLen);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Adds the CA to the cert store when requesting Server or Client authentication.
 | |
| 
 | |
|   This function adds the CA certificate to the list of CAs when requesting
 | |
|   Server or Client authentication for the chosen TLS connection.
 | |
| 
 | |
|   @param[in]  Tls         Pointer to the TLS object.
 | |
|   @param[in]  Data        Pointer to the data buffer of a DER-encoded binary
 | |
|                           X.509 certificate or PEM-encoded X.509 certificate.
 | |
|   @param[in]  DataSize    The size of data buffer in bytes.
 | |
| 
 | |
|   @retval  EFI_SUCCESS             The operation succeeded.
 | |
|   @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
 | |
|   @retval  EFI_OUT_OF_RESOURCES    Required resources could not be allocated.
 | |
|   @retval  EFI_ABORTED             Invalid X.509 certificate.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetCaCertificate (
 | |
|   IN     VOID   *Tls,
 | |
|   IN     VOID   *Data,
 | |
|   IN     UINTN  DataSize
 | |
|   )
 | |
| {
 | |
|   BIO             *BioCert;
 | |
|   X509            *Cert;
 | |
|   X509_STORE      *X509Store;
 | |
|   EFI_STATUS      Status;
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
|   SSL_CTX         *SslCtx;
 | |
|   INTN            Ret;
 | |
| 
 | |
|   BioCert   = NULL;
 | |
|   Cert      = NULL;
 | |
|   X509Store = NULL;
 | |
|   Status    = EFI_SUCCESS;
 | |
|   TlsConn   = (TLS_CONNECTION *)Tls;
 | |
|   Ret       = 0;
 | |
| 
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (Data == NULL) || (DataSize == 0)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.
 | |
|   // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.
 | |
|   //
 | |
|   Cert = d2i_X509 (NULL, (const unsigned char **)&Data, (long)DataSize);
 | |
|   if (Cert == NULL) {
 | |
|     //
 | |
|     // Certificate is from PEM encoding.
 | |
|     //
 | |
|     BioCert = BIO_new (BIO_s_mem ());
 | |
|     if (BioCert == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto ON_EXIT;
 | |
|     }
 | |
| 
 | |
|     if (BIO_write (BioCert, Data, (UINT32)DataSize) <= 0) {
 | |
|       Status = EFI_ABORTED;
 | |
|       goto ON_EXIT;
 | |
|     }
 | |
| 
 | |
|     Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);
 | |
|     if (Cert == NULL) {
 | |
|       Status = EFI_ABORTED;
 | |
|       goto ON_EXIT;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   SslCtx    = SSL_get_SSL_CTX (TlsConn->Ssl);
 | |
|   X509Store = SSL_CTX_get_cert_store (SslCtx);
 | |
|   if (X509Store == NULL) {
 | |
|     Status = EFI_ABORTED;
 | |
|     goto ON_EXIT;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Add certificate to X509 store
 | |
|   //
 | |
|   Ret = X509_STORE_add_cert (X509Store, Cert);
 | |
|   if (Ret != 1) {
 | |
|     unsigned long  ErrorCode;
 | |
| 
 | |
|     ErrorCode = ERR_peek_last_error ();
 | |
|     //
 | |
|     // Ignore "already in table" errors
 | |
|     //
 | |
|     if (!((ERR_GET_LIB (ErrorCode) == ERR_LIB_X509) &&
 | |
|           (ERR_GET_REASON (ErrorCode) == X509_R_CERT_ALREADY_IN_HASH_TABLE)))
 | |
|     {
 | |
|       Status = EFI_ABORTED;
 | |
|       goto ON_EXIT;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| ON_EXIT:
 | |
|   if (BioCert != NULL) {
 | |
|     BIO_free (BioCert);
 | |
|   }
 | |
| 
 | |
|   if (Cert != NULL) {
 | |
|     X509_free (Cert);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Loads the local public certificate into the specified TLS object.
 | |
| 
 | |
|   This function loads the X.509 certificate into the specified TLS object
 | |
|   for TLS negotiation.
 | |
| 
 | |
|   @param[in]  Tls         Pointer to the TLS object.
 | |
|   @param[in]  Data        Pointer to the data buffer of a DER-encoded binary
 | |
|                           X.509 certificate or PEM-encoded X.509 certificate.
 | |
|   @param[in]  DataSize    The size of data buffer in bytes.
 | |
| 
 | |
|   @retval  EFI_SUCCESS             The operation succeeded.
 | |
|   @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
 | |
|   @retval  EFI_OUT_OF_RESOURCES    Required resources could not be allocated.
 | |
|   @retval  EFI_ABORTED             Invalid X.509 certificate.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetHostPublicCert (
 | |
|   IN     VOID   *Tls,
 | |
|   IN     VOID   *Data,
 | |
|   IN     UINTN  DataSize
 | |
|   )
 | |
| {
 | |
|   BIO             *BioCert;
 | |
|   X509            *Cert;
 | |
|   EFI_STATUS      Status;
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
| 
 | |
|   BioCert = NULL;
 | |
|   Cert    = NULL;
 | |
|   Status  = EFI_SUCCESS;
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
| 
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (Data == NULL) || (DataSize == 0)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.
 | |
|   // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.
 | |
|   //
 | |
|   Cert = d2i_X509 (NULL, (const unsigned char **)&Data, (long)DataSize);
 | |
|   if (Cert == NULL) {
 | |
|     //
 | |
|     // Certificate is from PEM encoding.
 | |
|     //
 | |
|     BioCert = BIO_new (BIO_s_mem ());
 | |
|     if (BioCert == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto ON_EXIT;
 | |
|     }
 | |
| 
 | |
|     if (BIO_write (BioCert, Data, (UINT32)DataSize) <= 0) {
 | |
|       Status = EFI_ABORTED;
 | |
|       goto ON_EXIT;
 | |
|     }
 | |
| 
 | |
|     Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);
 | |
|     if (Cert == NULL) {
 | |
|       Status = EFI_ABORTED;
 | |
|       goto ON_EXIT;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (SSL_use_certificate (TlsConn->Ssl, Cert) != 1) {
 | |
|     Status = EFI_ABORTED;
 | |
|     goto ON_EXIT;
 | |
|   }
 | |
| 
 | |
| ON_EXIT:
 | |
|   if (BioCert != NULL) {
 | |
|     BIO_free (BioCert);
 | |
|   }
 | |
| 
 | |
|   if (Cert != NULL) {
 | |
|     X509_free (Cert);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Adds the local private key to the specified TLS object.
 | |
| 
 | |
|   This function adds the local private key (DER-encoded or PEM-encoded or PKCS#8 private
 | |
|   key) into the specified TLS object for TLS negotiation.
 | |
| 
 | |
|   @param[in]  Tls         Pointer to the TLS object.
 | |
|   @param[in]  Data        Pointer to the data buffer of a DER-encoded or PEM-encoded
 | |
|                           or PKCS#8 private key.
 | |
|   @param[in]  DataSize    The size of data buffer in bytes.
 | |
|   @param[in]  Password    Pointer to NULL-terminated private key password, set it to NULL
 | |
|                           if private key not encrypted.
 | |
| 
 | |
|   @retval  EFI_SUCCESS     The operation succeeded.
 | |
|   @retval  EFI_UNSUPPORTED This function is not supported.
 | |
|   @retval  EFI_ABORTED     Invalid private key data.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetHostPrivateKeyEx (
 | |
|   IN     VOID   *Tls,
 | |
|   IN     VOID   *Data,
 | |
|   IN     UINTN  DataSize,
 | |
|   IN     VOID   *Password  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
|   BIO             *Bio;
 | |
|   EVP_PKEY        *Pkey;
 | |
|   BOOLEAN         Verify;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
| 
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (Data == NULL) || (DataSize == 0)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   // Try to parse the private key in DER format or un-encrypted PKC#8
 | |
|   if (SSL_use_PrivateKey_ASN1 (
 | |
|         EVP_PKEY_RSA,
 | |
|         TlsConn->Ssl,
 | |
|         Data,
 | |
|         (long)DataSize
 | |
|         ) == 1)
 | |
|   {
 | |
|     goto verify;
 | |
|   }
 | |
| 
 | |
|   if (SSL_use_PrivateKey_ASN1 (
 | |
|         EVP_PKEY_DSA,
 | |
|         TlsConn->Ssl,
 | |
|         Data,
 | |
|         (long)DataSize
 | |
|         ) == 1)
 | |
|   {
 | |
|     goto verify;
 | |
|   }
 | |
| 
 | |
|   if (SSL_use_PrivateKey_ASN1 (
 | |
|         EVP_PKEY_EC,
 | |
|         TlsConn->Ssl,
 | |
|         Data,
 | |
|         (long)DataSize
 | |
|         ) == 1)
 | |
|   {
 | |
|     goto verify;
 | |
|   }
 | |
| 
 | |
|   // Try to parse the private key in PEM format or encrypted PKC#8
 | |
|   Bio = BIO_new_mem_buf (Data, (int)DataSize);
 | |
|   if (Bio != NULL) {
 | |
|     Verify = FALSE;
 | |
|     Pkey   = PEM_read_bio_PrivateKey (Bio, NULL, NULL, Password);
 | |
|     if ((Pkey != NULL) && (SSL_use_PrivateKey (TlsConn->Ssl, Pkey) == 1)) {
 | |
|       Verify = TRUE;
 | |
|     }
 | |
| 
 | |
|     EVP_PKEY_free (Pkey);
 | |
|     BIO_free (Bio);
 | |
| 
 | |
|     if (Verify) {
 | |
|       goto verify;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_ABORTED;
 | |
| 
 | |
| verify:
 | |
|   if (SSL_check_private_key (TlsConn->Ssl) == 1) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   return EFI_ABORTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Adds the local private key to the specified TLS object.
 | |
| 
 | |
|   This function adds the local private key (DER-encoded or PEM-encoded or PKCS#8 private
 | |
|   key) into the specified TLS object for TLS negotiation.
 | |
| 
 | |
|   @param[in]  Tls         Pointer to the TLS object.
 | |
|   @param[in]  Data        Pointer to the data buffer of a DER-encoded or PEM-encoded
 | |
|                           or PKCS#8 private key.
 | |
|   @param[in]  DataSize    The size of data buffer in bytes.
 | |
| 
 | |
|   @retval  EFI_SUCCESS     The operation succeeded.
 | |
|   @retval  EFI_UNSUPPORTED This function is not supported.
 | |
|   @retval  EFI_ABORTED     Invalid private key data.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetHostPrivateKey (
 | |
|   IN     VOID   *Tls,
 | |
|   IN     VOID   *Data,
 | |
|   IN     UINTN  DataSize
 | |
|   )
 | |
| {
 | |
|   return TlsSetHostPrivateKeyEx (Tls, Data, DataSize, NULL);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Adds the CA-supplied certificate revocation list for certificate validation.
 | |
| 
 | |
|   This function adds the CA-supplied certificate revocation list data for
 | |
|   certificate validity checking.
 | |
| 
 | |
|   @param[in]  Data        Pointer to the data buffer of a DER-encoded CRL data.
 | |
|   @param[in]  DataSize    The size of data buffer in bytes.
 | |
| 
 | |
|   @retval  EFI_SUCCESS     The operation succeeded.
 | |
|   @retval  EFI_UNSUPPORTED This function is not supported.
 | |
|   @retval  EFI_ABORTED     Invalid CRL data.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetCertRevocationList (
 | |
|   IN     VOID   *Data,
 | |
|   IN     UINTN  DataSize
 | |
|   )
 | |
| {
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set the signature algorithm list to used by the TLS object.
 | |
| 
 | |
|   This function sets the signature algorithms for use by a specified TLS object.
 | |
| 
 | |
|   @param[in]  Tls                Pointer to a TLS object.
 | |
|   @param[in]  Data               Array of UINT8 of signature algorithms. The array consists of
 | |
|                                  pairs of the hash algorithm and the signature algorithm as defined
 | |
|                                  in RFC 5246
 | |
|   @param[in]  DataSize           The length the SignatureAlgoList. Must be divisible by 2.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           The signature algorithm list was set successfully.
 | |
|   @retval  EFI_INVALID_PARAMETER The parameters are invalid.
 | |
|   @retval  EFI_UNSUPPORTED       No supported TLS signature algorithm was found in SignatureAlgoList
 | |
|   @retval  EFI_OUT_OF_RESOURCES  Memory allocation failed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetSignatureAlgoList (
 | |
|   IN     VOID   *Tls,
 | |
|   IN     UINT8  *Data,
 | |
|   IN     UINTN  DataSize
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
|   UINTN           Index;
 | |
|   UINTN           SignAlgoStrSize;
 | |
|   CHAR8           *SignAlgoStr;
 | |
|   CHAR8           *Pos;
 | |
|   UINT8           *SignatureAlgoList;
 | |
|   EFI_STATUS      Status;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
| 
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (Data == NULL) || (DataSize < 3) ||
 | |
|       ((DataSize % 2) == 0) || (Data[0] != DataSize - 1))
 | |
|   {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   SignatureAlgoList = Data + 1;
 | |
|   SignAlgoStrSize   = 0;
 | |
|   for (Index = 0; Index < Data[0]; Index += 2) {
 | |
|     CONST CHAR8  *Tmp;
 | |
| 
 | |
|     if (SignatureAlgoList[Index] >= ARRAY_SIZE (TlsHashAlgoToName)) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     Tmp = TlsHashAlgoToName[SignatureAlgoList[Index]].Name;
 | |
|     if (!Tmp) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     // Add 1 for the '+'
 | |
|     SignAlgoStrSize += AsciiStrLen (Tmp) + 1;
 | |
| 
 | |
|     if (SignatureAlgoList[Index + 1] >= ARRAY_SIZE (TlsSignatureAlgoToName)) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     Tmp = TlsSignatureAlgoToName[SignatureAlgoList[Index + 1]].Name;
 | |
|     if (!Tmp) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     // Add 1 for the ':' or for the NULL terminator
 | |
|     SignAlgoStrSize += AsciiStrLen (Tmp) + 1;
 | |
|   }
 | |
| 
 | |
|   if (!SignAlgoStrSize) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   SignAlgoStr = AllocatePool (SignAlgoStrSize);
 | |
|   if (SignAlgoStr == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Pos = SignAlgoStr;
 | |
|   for (Index = 0; Index < Data[0]; Index += 2) {
 | |
|     CONST CHAR8  *Tmp;
 | |
| 
 | |
|     Tmp = TlsHashAlgoToName[SignatureAlgoList[Index]].Name;
 | |
|     CopyMem (Pos, Tmp, AsciiStrLen (Tmp));
 | |
|     Pos   += AsciiStrLen (Tmp);
 | |
|     *Pos++ = '+';
 | |
| 
 | |
|     Tmp = TlsSignatureAlgoToName[SignatureAlgoList[Index + 1]].Name;
 | |
|     CopyMem (Pos, Tmp, AsciiStrLen (Tmp));
 | |
|     Pos   += AsciiStrLen (Tmp);
 | |
|     *Pos++ = ':';
 | |
|   }
 | |
| 
 | |
|   *(Pos - 1) = '\0';
 | |
| 
 | |
|   if (SSL_set1_sigalgs_list (TlsConn->Ssl, SignAlgoStr) < 1) {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|   } else {
 | |
|     Status = EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   FreePool (SignAlgoStr);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set the EC curve to be used for TLS flows
 | |
| 
 | |
|   This function sets the EC curve to be used for TLS flows.
 | |
| 
 | |
|   @param[in]  Tls                Pointer to a TLS object.
 | |
|   @param[in]  Data               An EC named curve as defined in section 5.1.1 of RFC 4492.
 | |
|   @param[in]  DataSize           Size of Data, it should be sizeof (UINT32)
 | |
| 
 | |
|   @retval  EFI_SUCCESS           The EC curve was set successfully.
 | |
|   @retval  EFI_INVALID_PARAMETER The parameters are invalid.
 | |
|   @retval  EFI_UNSUPPORTED       The requested TLS EC curve is not supported
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetEcCurve (
 | |
|   IN     VOID   *Tls,
 | |
|   IN     UINT8  *Data,
 | |
|   IN     UINTN  DataSize
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
|   EC_KEY          *EcKey;
 | |
|   INT32           Nid;
 | |
|   INT32           Ret;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
| 
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (Data == NULL) || (DataSize != sizeof (UINT32))) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   switch (*((UINT32 *)Data)) {
 | |
|     case TlsEcNamedCurveSecp256r1:
 | |
|       return EFI_UNSUPPORTED;
 | |
|     case TlsEcNamedCurveSecp384r1:
 | |
|       Nid = NID_secp384r1;
 | |
|       break;
 | |
|     case TlsEcNamedCurveSecp521r1:
 | |
|       Nid = NID_secp521r1;
 | |
|       break;
 | |
|     case TlsEcNamedCurveX25519:
 | |
|       Nid = NID_X25519;
 | |
|       break;
 | |
|     case TlsEcNamedCurveX448:
 | |
|       Nid = NID_X448;
 | |
|       break;
 | |
|     default:
 | |
|       return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   if (SSL_set1_curves (TlsConn->Ssl, &Nid, 1) != 1) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   EcKey = EC_KEY_new_by_curve_name (Nid);
 | |
|   if (EcKey == NULL) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   Ret = SSL_set_tmp_ecdh (TlsConn->Ssl, EcKey);
 | |
|   EC_KEY_free (EcKey);
 | |
| 
 | |
|   if (Ret != 1) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set the Tls security level.
 | |
| 
 | |
|   This function Set the Tls security level.
 | |
|   If Tls is NULL, nothing is done.
 | |
| 
 | |
|   @param[in]  Tls                Pointer to the TLS object.
 | |
|   @param[in]  Level              Tls Security level need to set.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           The Tls security level was set successfully.
 | |
|   @retval  EFI_INVALID_PARAMETER The parameters are invalid.
 | |
|   @retval  EFI_UNSUPPORTED       The requested TLS set security level is not supported.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsSetSecurityLevel (
 | |
|   IN VOID   *Tls,
 | |
|   IN UINT8  Level
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
| 
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   // Check if the security level is within the valid range (2 to 5).
 | |
|   // Return EFI_INVALID_PARAMETER if the level is out of bounds.
 | |
|   if ((Level < MIN_SECURITY_LEVEL) || (Level > MAX_SECURITY_LEVEL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   SSL_set_security_level (TlsConn->Ssl, Level);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gets the protocol version used by the specified TLS connection.
 | |
| 
 | |
|   This function returns the protocol version used by the specified TLS
 | |
|   connection.
 | |
| 
 | |
|   If Tls is NULL, then ASSERT().
 | |
| 
 | |
|   @param[in]  Tls    Pointer to the TLS object.
 | |
| 
 | |
|   @return  The protocol version of the specified TLS connection.
 | |
| 
 | |
| **/
 | |
| UINT16
 | |
| EFIAPI
 | |
| TlsGetVersion (
 | |
|   IN     VOID  *Tls
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
| 
 | |
|   if (TlsConn == NULL) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   return (UINT16)(SSL_version (TlsConn->Ssl));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gets the connection end of the specified TLS connection.
 | |
| 
 | |
|   This function returns the connection end (as client or as server) used by
 | |
|   the specified TLS connection.
 | |
| 
 | |
|   If Tls is NULL, then ASSERT().
 | |
| 
 | |
|   @param[in]  Tls    Pointer to the TLS object.
 | |
| 
 | |
|   @return  The connection end used by the specified TLS connection.
 | |
| 
 | |
| **/
 | |
| UINT8
 | |
| EFIAPI
 | |
| TlsGetConnectionEnd (
 | |
|   IN     VOID  *Tls
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
| 
 | |
|   if (TlsConn == NULL) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   return (UINT8)SSL_is_server (TlsConn->Ssl);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gets the cipher suite used by the specified TLS connection.
 | |
| 
 | |
|   This function returns current cipher suite used by the specified
 | |
|   TLS connection.
 | |
| 
 | |
|   @param[in]      Tls         Pointer to the TLS object.
 | |
|   @param[in,out]  CipherId    The cipher suite used by the TLS object.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           The cipher suite was returned successfully.
 | |
|   @retval  EFI_INVALID_PARAMETER The parameter is invalid.
 | |
|   @retval  EFI_UNSUPPORTED       Unsupported cipher suite.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsGetCurrentCipher (
 | |
|   IN     VOID    *Tls,
 | |
|   IN OUT UINT16  *CipherId
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION    *TlsConn;
 | |
|   CONST SSL_CIPHER  *Cipher;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
|   Cipher  = NULL;
 | |
| 
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (CipherId == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Cipher = SSL_get_current_cipher (TlsConn->Ssl);
 | |
|   if (Cipher == NULL) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   *CipherId = (SSL_CIPHER_get_id (Cipher)) & 0xFFFF;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gets the compression methods used by the specified TLS connection.
 | |
| 
 | |
|   This function returns current integrated compression methods used by
 | |
|   the specified TLS connection.
 | |
| 
 | |
|   @param[in]      Tls              Pointer to the TLS object.
 | |
|   @param[in,out]  CompressionId    The current compression method used by
 | |
|                                    the TLS object.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           The compression method was returned successfully.
 | |
|   @retval  EFI_INVALID_PARAMETER The parameter is invalid.
 | |
|   @retval  EFI_ABORTED           Invalid Compression method.
 | |
|   @retval  EFI_UNSUPPORTED       This function is not supported.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsGetCurrentCompressionId (
 | |
|   IN     VOID   *Tls,
 | |
|   IN OUT UINT8  *CompressionId
 | |
|   )
 | |
| {
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gets the verification mode currently set in the TLS connection.
 | |
| 
 | |
|   This function returns the peer verification mode currently set in the
 | |
|   specified TLS connection.
 | |
| 
 | |
|   If Tls is NULL, then ASSERT().
 | |
| 
 | |
|   @param[in]  Tls    Pointer to the TLS object.
 | |
| 
 | |
|   @return  The verification mode set in the specified TLS connection.
 | |
| 
 | |
| **/
 | |
| UINT32
 | |
| EFIAPI
 | |
| TlsGetVerify (
 | |
|   IN     VOID  *Tls
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
| 
 | |
|   if (TlsConn == NULL) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   return SSL_get_verify_mode (TlsConn->Ssl);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gets the session ID used by the specified TLS connection.
 | |
| 
 | |
|   This function returns the TLS/SSL session ID currently used by the
 | |
|   specified TLS connection.
 | |
| 
 | |
|   @param[in]      Tls             Pointer to the TLS object.
 | |
|   @param[in,out]  SessionId       Buffer to contain the returned session ID.
 | |
|   @param[in,out]  SessionIdLen    The length of Session ID in bytes.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           The Session ID was returned successfully.
 | |
|   @retval  EFI_INVALID_PARAMETER The parameter is invalid.
 | |
|   @retval  EFI_UNSUPPORTED       Invalid TLS/SSL session.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsGetSessionId (
 | |
|   IN     VOID    *Tls,
 | |
|   IN OUT UINT8   *SessionId,
 | |
|   IN OUT UINT16  *SessionIdLen
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
|   SSL_SESSION     *Session;
 | |
|   CONST UINT8     *SslSessionId;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
|   Session = NULL;
 | |
| 
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (SessionId == NULL) || (SessionIdLen == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Session = SSL_get_session (TlsConn->Ssl);
 | |
|   if (Session == NULL) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   SslSessionId = SSL_SESSION_get_id (Session, (unsigned int *)SessionIdLen);
 | |
|   CopyMem (SessionId, SslSessionId, *SessionIdLen);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gets the client random data used in the specified TLS connection.
 | |
| 
 | |
|   This function returns the TLS/SSL client random data currently used in
 | |
|   the specified TLS connection.
 | |
| 
 | |
|   @param[in]      Tls             Pointer to the TLS object.
 | |
|   @param[in,out]  ClientRandom    Buffer to contain the returned client
 | |
|                                   random data (32 bytes).
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| TlsGetClientRandom (
 | |
|   IN     VOID   *Tls,
 | |
|   IN OUT UINT8  *ClientRandom
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
| 
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (ClientRandom == NULL)) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   SSL_get_client_random (TlsConn->Ssl, ClientRandom, SSL3_RANDOM_SIZE);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gets the server random data used in the specified TLS connection.
 | |
| 
 | |
|   This function returns the TLS/SSL server random data currently used in
 | |
|   the specified TLS connection.
 | |
| 
 | |
|   @param[in]      Tls             Pointer to the TLS object.
 | |
|   @param[in,out]  ServerRandom    Buffer to contain the returned server
 | |
|                                   random data (32 bytes).
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| TlsGetServerRandom (
 | |
|   IN     VOID   *Tls,
 | |
|   IN OUT UINT8  *ServerRandom
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
| 
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (ServerRandom == NULL)) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   SSL_get_server_random (TlsConn->Ssl, ServerRandom, SSL3_RANDOM_SIZE);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gets the master key data used in the specified TLS connection.
 | |
| 
 | |
|   This function returns the TLS/SSL master key material currently used in
 | |
|   the specified TLS connection.
 | |
| 
 | |
|   @param[in]      Tls            Pointer to the TLS object.
 | |
|   @param[in,out]  KeyMaterial    Buffer to contain the returned key material.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           Key material was returned successfully.
 | |
|   @retval  EFI_INVALID_PARAMETER The parameter is invalid.
 | |
|   @retval  EFI_UNSUPPORTED       Invalid TLS/SSL session.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsGetKeyMaterial (
 | |
|   IN     VOID   *Tls,
 | |
|   IN OUT UINT8  *KeyMaterial
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
|   SSL_SESSION     *Session;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
|   Session = NULL;
 | |
| 
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (KeyMaterial == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Session = SSL_get_session (TlsConn->Ssl);
 | |
| 
 | |
|   if (Session == NULL) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   SSL_SESSION_get_master_key (Session, KeyMaterial, SSL3_MASTER_SECRET_SIZE);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gets the CA Certificate from the cert store.
 | |
| 
 | |
|   This function returns the CA certificate for the chosen
 | |
|   TLS connection.
 | |
| 
 | |
|   @param[in]      Tls         Pointer to the TLS object.
 | |
|   @param[out]     Data        Pointer to the data buffer to receive the CA
 | |
|                               certificate data sent to the client.
 | |
|   @param[in,out]  DataSize    The size of data buffer in bytes.
 | |
| 
 | |
|   @retval  EFI_SUCCESS             The operation succeeded.
 | |
|   @retval  EFI_UNSUPPORTED         This function is not supported.
 | |
|   @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsGetCaCertificate (
 | |
|   IN     VOID   *Tls,
 | |
|   OUT    VOID   *Data,
 | |
|   IN OUT UINTN  *DataSize
 | |
|   )
 | |
| {
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gets the local public Certificate set in the specified TLS object.
 | |
| 
 | |
|   This function returns the local public certificate which was currently set
 | |
|   in the specified TLS object.
 | |
| 
 | |
|   @param[in]      Tls         Pointer to the TLS object.
 | |
|   @param[out]     Data        Pointer to the data buffer to receive the local
 | |
|                               public certificate.
 | |
|   @param[in,out]  DataSize    The size of data buffer in bytes.
 | |
| 
 | |
|   @retval  EFI_SUCCESS             The operation succeeded.
 | |
|   @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
 | |
|   @retval  EFI_NOT_FOUND           The certificate is not found.
 | |
|   @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsGetHostPublicCert (
 | |
|   IN     VOID   *Tls,
 | |
|   OUT    VOID   *Data,
 | |
|   IN OUT UINTN  *DataSize
 | |
|   )
 | |
| {
 | |
|   X509            *Cert;
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
| 
 | |
|   Cert    = NULL;
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
| 
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL) || (DataSize == NULL) || ((*DataSize != 0) && (Data == NULL))) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Cert = SSL_get_certificate (TlsConn->Ssl);
 | |
|   if (Cert == NULL) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Only DER encoding is supported currently.
 | |
|   //
 | |
|   if (*DataSize < (UINTN)i2d_X509 (Cert, NULL)) {
 | |
|     *DataSize = (UINTN)i2d_X509 (Cert, NULL);
 | |
|     return EFI_BUFFER_TOO_SMALL;
 | |
|   }
 | |
| 
 | |
|   *DataSize = (UINTN)i2d_X509 (Cert, (unsigned char **)&Data);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gets the local private key set in the specified TLS object.
 | |
| 
 | |
|   This function returns the local private key data which was currently set
 | |
|   in the specified TLS object.
 | |
| 
 | |
|   @param[in]      Tls         Pointer to the TLS object.
 | |
|   @param[out]     Data        Pointer to the data buffer to receive the local
 | |
|                               private key data.
 | |
|   @param[in,out]  DataSize    The size of data buffer in bytes.
 | |
| 
 | |
|   @retval  EFI_SUCCESS             The operation succeeded.
 | |
|   @retval  EFI_UNSUPPORTED         This function is not supported.
 | |
|   @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsGetHostPrivateKey (
 | |
|   IN     VOID   *Tls,
 | |
|   OUT    VOID   *Data,
 | |
|   IN OUT UINTN  *DataSize
 | |
|   )
 | |
| {
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gets the CA-supplied certificate revocation list data set in the specified
 | |
|   TLS object.
 | |
| 
 | |
|   This function returns the CA-supplied certificate revocation list data which
 | |
|   was currently set in the specified TLS object.
 | |
| 
 | |
|   @param[out]     Data        Pointer to the data buffer to receive the CRL data.
 | |
|   @param[in,out]  DataSize    The size of data buffer in bytes.
 | |
| 
 | |
|   @retval  EFI_SUCCESS             The operation succeeded.
 | |
|   @retval  EFI_UNSUPPORTED         This function is not supported.
 | |
|   @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsGetCertRevocationList (
 | |
|   OUT    VOID   *Data,
 | |
|   IN OUT UINTN  *DataSize
 | |
|   )
 | |
| {
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Derive keying material from a TLS connection.
 | |
| 
 | |
|   This function exports keying material using the mechanism described in RFC
 | |
|   5705.
 | |
| 
 | |
|   @param[in]      Tls          Pointer to the TLS object
 | |
|   @param[in]      Label        Description of the key for the PRF function
 | |
|   @param[in]      Context      Optional context
 | |
|   @param[in]      ContextLen   The length of the context value in bytes
 | |
|   @param[out]     KeyBuffer    Buffer to hold the output of the TLS-PRF
 | |
|   @param[in]      KeyBufferLen The length of the KeyBuffer
 | |
| 
 | |
|   @retval  EFI_SUCCESS             The operation succeeded.
 | |
|   @retval  EFI_INVALID_PARAMETER   The TLS object is invalid.
 | |
|   @retval  EFI_PROTOCOL_ERROR      Some other error occurred.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| TlsGetExportKey (
 | |
|   IN     VOID        *Tls,
 | |
|   IN     CONST VOID  *Label,
 | |
|   IN     CONST VOID  *Context,
 | |
|   IN     UINTN       ContextLen,
 | |
|   OUT    VOID        *KeyBuffer,
 | |
|   IN     UINTN       KeyBufferLen
 | |
|   )
 | |
| {
 | |
|   TLS_CONNECTION  *TlsConn;
 | |
| 
 | |
|   TlsConn = (TLS_CONNECTION *)Tls;
 | |
| 
 | |
|   if ((TlsConn == NULL) || (TlsConn->Ssl == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   return SSL_export_keying_material (
 | |
|            TlsConn->Ssl,
 | |
|            KeyBuffer,
 | |
|            KeyBufferLen,
 | |
|            Label,
 | |
|            AsciiStrLen (Label),
 | |
|            Context,
 | |
|            ContextLen,
 | |
|            Context != NULL
 | |
|            ) == 1 ?
 | |
|          EFI_SUCCESS : EFI_PROTOCOL_ERROR;
 | |
| }
 |