[edk2-devel] [PATCH V2 2/3] CryptoPkg: Extend Tls function library

Li, Yi yi1.li at intel.com
Sat Oct 8 02:09:38 UTC 2022


REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3892

1. TlsSetSignatureAlgoList(): Configure the list of TLS signature algorithms
that should be used as part of the TLS session establishment.
This is needed for some WLAN Supplicant connection establishment flows
that allow only specific TLS signature algorithms to be used, e.g.,
Authenticate and Key Managmenet (AKM) suites that are SUITE-B compliant.

2. TlsSetEcCurve(): Configure the Elliptic Curve that should be used for
TLS flows the use cipher suite with EC,
e.g., TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384.
This is needed for some WLAN Supplicant connection establishment flows
that allow only specific TLS signature algorithms to be used,
e.g., Authenticate and Key Managmenet (AKM) suites that are SUITE-B compliant.

3. TlsShutdown():
Shutdown the TLS connection without releasing the resources,
meaning a new connection can be started without calling TlsNew() and
without setting certificates etc.

4. TlsGetExportKey(): Derive keying material from a TLS connection using the
mechanism described in RFC 5705 and export the key material (needed
by EAP methods such as EAP-TTLS and EAP-PEAP).

5. TlsSetHostPrivateKeyEx(): This function adds the local private key
(PEM-encoded or PKCS#8 or DER-encoded private key) into the specified
TLS object for TLS negotiation. There is already a similar function
TlsSetHostPrivateKey(), the new Ex function introduces a new parameter
Password, set Password to NULL when useless.

Cc: Jiewen Yao <jiewen.yao at intel.com>
Cc: Jian J Wang <jian.j.wang at intel.com>
Cc: Xiaoyu Lu <xiaoyu1.lu at intel.com>
Cc: Guomin Jiang <guomin.jiang at intel.com>
Signed-off-by: Yi Li <yi1.li at intel.com>
---
 CryptoPkg/Include/Library/TlsLib.h            | 126 +++++-
 CryptoPkg/Library/TlsLib/InternalTlsLib.h     |   4 +
 CryptoPkg/Library/TlsLib/TlsConfig.c          | 412 ++++++++++++++++--
 CryptoPkg/Library/TlsLib/TlsProcess.c         |  32 ++
 CryptoPkg/Library/TlsLibNull/TlsConfigNull.c  | 123 +++++-
 CryptoPkg/Library/TlsLibNull/TlsProcessNull.c |  23 +
 6 files changed, 690 insertions(+), 30 deletions(-)

diff --git a/CryptoPkg/Include/Library/TlsLib.h b/CryptoPkg/Include/Library/TlsLib.h
index 3b75fde0aa..d37c5fcc35 100644
--- a/CryptoPkg/Include/Library/TlsLib.h
+++ b/CryptoPkg/Include/Library/TlsLib.h
@@ -294,6 +294,25 @@ TlsWrite (
   IN     UINTN  BufferSize
   );
 
+/**
+  Shutdown a TLS connection.
+
+  Shutdown the TLS connection without releasing the resources, meaning a new
+  connection can be started without calling TlsNew() and without setting
+  certificates etc.
+
+  @param[in]       Tls            Pointer to the TLS object to shutdown.
+
+  @retval EFI_SUCCESS             The TLS is shutdown successfully.
+  @retval EFI_INVALID_PARAMETER   Tls is NULL.
+  @retval EFI_PROTOCOL_ERROR      Some other error occurred.
+**/
+EFI_STATUS
+EFIAPI
+TlsShutdown (
+  IN     VOID  *Tls
+  );
+
 /**
   Set a new TLS/SSL method for a particular TLS object.
 
@@ -492,11 +511,38 @@ TlsSetHostPublicCert (
 /**
   Adds the local private key to the specified TLS object.
 
-  This function adds the local private key (PEM-encoded RSA or PKCS#8 private
+  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 PEM-encoded RSA
+  @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
+  );
+
+/**
+  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.
 
@@ -534,6 +580,53 @@ TlsSetCertRevocationList (
   IN     UINTN  DataSize
   );
 
+/**
+  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
+  );
+
+/**
+  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
+  );
+
 /**
   Gets the protocol version used by the specified TLS connection.
 
@@ -810,4 +903,33 @@ TlsGetCertRevocationList (
   IN OUT UINTN  *DataSize
   );
 
+/**
+  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
+  );
+
 #endif // __TLS_LIB_H__
diff --git a/CryptoPkg/Library/TlsLib/InternalTlsLib.h b/CryptoPkg/Library/TlsLib/InternalTlsLib.h
index cf5ffe1b73..97a46af6c1 100644
--- a/CryptoPkg/Library/TlsLib/InternalTlsLib.h
+++ b/CryptoPkg/Library/TlsLib/InternalTlsLib.h
@@ -17,6 +17,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/DebugLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/SafeIntLib.h>
+#include <Protocol/Tls.h>
+#include <IndustryStandard/Tls1.h>
+#include <Library/PcdLib.h>
+#include <openssl/obj_mac.h>
 #include <openssl/ssl.h>
 #include <openssl/bio.h>
 #include <openssl/err.h>
diff --git a/CryptoPkg/Library/TlsLib/TlsConfig.c b/CryptoPkg/Library/TlsLib/TlsConfig.c
index 0673c9d532..eef8a3681f 100644
--- a/CryptoPkg/Library/TlsLib/TlsConfig.c
+++ b/CryptoPkg/Library/TlsLib/TlsConfig.c
@@ -39,29 +39,61 @@ typedef struct {
 // Keep the table uniquely sorted by the IanaCipher field, in increasing order.
 //
 STATIC CONST TLS_CIPHER_MAPPING  TlsCipherMappingTable[] = {
-  MAP (0x0001, "NULL-MD5"),                         /// TLS_RSA_WITH_NULL_MD5
-  MAP (0x0002, "NULL-SHA"),                         /// TLS_RSA_WITH_NULL_SHA
-  MAP (0x0004, "RC4-MD5"),                          /// TLS_RSA_WITH_RC4_128_MD5
-  MAP (0x0005, "RC4-SHA"),                          /// TLS_RSA_WITH_RC4_128_SHA
-  MAP (0x000A, "DES-CBC3-SHA"),                     /// TLS_RSA_WITH_3DES_EDE_CBC_SHA, mandatory TLS 1.1
-  MAP (0x0016, "DHE-RSA-DES-CBC3-SHA"),             /// TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
-  MAP (0x002F, "AES128-SHA"),                       /// TLS_RSA_WITH_AES_128_CBC_SHA, mandatory TLS 1.2
-  MAP (0x0030, "DH-DSS-AES128-SHA"),                /// TLS_DH_DSS_WITH_AES_128_CBC_SHA
-  MAP (0x0031, "DH-RSA-AES128-SHA"),                /// TLS_DH_RSA_WITH_AES_128_CBC_SHA
-  MAP (0x0033, "DHE-RSA-AES128-SHA"),               /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA
-  MAP (0x0035, "AES256-SHA"),                       /// TLS_RSA_WITH_AES_256_CBC_SHA
-  MAP (0x0036, "DH-DSS-AES256-SHA"),                /// TLS_DH_DSS_WITH_AES_256_CBC_SHA
-  MAP (0x0037, "DH-RSA-AES256-SHA"),                /// TLS_DH_RSA_WITH_AES_256_CBC_SHA
-  MAP (0x0039, "DHE-RSA-AES256-SHA"),               /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA
-  MAP (0x003B, "NULL-SHA256"),                      /// TLS_RSA_WITH_NULL_SHA256
-  MAP (0x003C, "AES128-SHA256"),                    /// TLS_RSA_WITH_AES_128_CBC_SHA256
-  MAP (0x003D, "AES256-SHA256"),                    /// TLS_RSA_WITH_AES_256_CBC_SHA256
-  MAP (0x003E, "DH-DSS-AES128-SHA256"),             /// TLS_DH_DSS_WITH_AES_128_CBC_SHA256
-  MAP (0x003F, "DH-RSA-AES128-SHA256"),             /// TLS_DH_RSA_WITH_AES_128_CBC_SHA256
-  MAP (0x0067, "DHE-RSA-AES128-SHA256"),            /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
-  MAP (0x0068, "DH-DSS-AES256-SHA256"),             /// TLS_DH_DSS_WITH_AES_256_CBC_SHA256
-  MAP (0x0069, "DH-RSA-AES256-SHA256"),             /// TLS_DH_RSA_WITH_AES_256_CBC_SHA256
-  MAP (0x006B, "DHE-RSA-AES256-SHA256"),            /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+  MAP (0x0001, "NULL-MD5"),                                /// TLS_RSA_WITH_NULL_MD5
+  MAP (0x0002, "NULL-SHA"),                                /// TLS_RSA_WITH_NULL_SHA
+  MAP (0x0004, "RC4-MD5"),                                 /// TLS_RSA_WITH_RC4_128_MD5
+  MAP (0x0005, "RC4-SHA"),                                 /// TLS_RSA_WITH_RC4_128_SHA
+  MAP (0x000A, "DES-CBC3-SHA"),                            /// TLS_RSA_WITH_3DES_EDE_CBC_SHA, mandatory TLS 1.1
+  MAP (0x0016, "DHE-RSA-DES-CBC3-SHA"),                    /// TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+  MAP (0x002F, "AES128-SHA"),                              /// TLS_RSA_WITH_AES_128_CBC_SHA, mandatory TLS 1.2
+  MAP (0x0030, "DH-DSS-AES128-SHA"),                       /// TLS_DH_DSS_WITH_AES_128_CBC_SHA
+  MAP (0x0031, "DH-RSA-AES128-SHA"),                       /// TLS_DH_RSA_WITH_AES_128_CBC_SHA
+  MAP (0x0033, "DHE-RSA-AES128-SHA"),                      /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+  MAP (0x0035, "AES256-SHA"),                              /// TLS_RSA_WITH_AES_256_CBC_SHA
+  MAP (0x0036, "DH-DSS-AES256-SHA"),                       /// TLS_DH_DSS_WITH_AES_256_CBC_SHA
+  MAP (0x0037, "DH-RSA-AES256-SHA"),                       /// TLS_DH_RSA_WITH_AES_256_CBC_SHA
+  MAP (0x0039, "DHE-RSA-AES256-SHA"),                      /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+  MAP (0x003B, "NULL-SHA256"),                             /// TLS_RSA_WITH_NULL_SHA256
+  MAP (0x003C, "AES128-SHA256"),                           /// TLS_RSA_WITH_AES_128_CBC_SHA256
+  MAP (0x003D, "AES256-SHA256"),                           /// TLS_RSA_WITH_AES_256_CBC_SHA256
+  MAP (0x003E, "DH-DSS-AES128-SHA256"),                    /// TLS_DH_DSS_WITH_AES_128_CBC_SHA256
+  MAP (0x003F, "DH-RSA-AES128-SHA256"),                    /// TLS_DH_RSA_WITH_AES_128_CBC_SHA256
+  MAP (0x0067, "DHE-RSA-AES128-SHA256"),                   /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+  MAP (0x0068, "DH-DSS-AES256-SHA256"),                    /// TLS_DH_DSS_WITH_AES_256_CBC_SHA256
+  MAP (0x0069, "DH-RSA-AES256-SHA256"),                    /// TLS_DH_RSA_WITH_AES_256_CBC_SHA256
+  MAP (0x006B, "DHE-RSA-AES256-SHA256"),                   /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+  MAP (0x009F, "DHE-RSA-AES256-GCM-SHA384"),               /// TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+  MAP (0xC02B, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"), /// TLS_ECDHE_ECDSA_AES128_GCM_SHA256
+  MAP (0xC02C, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"), /// TLS_ECDHE_ECDSA_AES256_GCM_SHA384
+  MAP (0xC030, "ECDHE-RSA-AES256-GCM-SHA384"),             /// TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+};
+
+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" },
 };
 
 /**
@@ -831,11 +863,107 @@ ON_EXIT:
 /**
   Adds the local private key to the specified TLS object.
 
-  This function adds the local private key (PEM-encoded RSA or PKCS#8 private
+  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 PEM-encoded RSA
+  @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.
 
@@ -852,7 +980,7 @@ TlsSetHostPrivateKey (
   IN     UINTN  DataSize
   )
 {
-  return EFI_UNSUPPORTED;
+  return TlsSetHostPrivateKeyEx (Tls, Data, DataSize, NULL);
 }
 
 /**
@@ -879,6 +1007,188 @@ TlsSetCertRevocationList (
   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
+  )
+{
+ #if !FixedPcdGetBool (PcdOpensslEcEnabled)
+  return EFI_UNSUPPORTED;
+ #else
+  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_INVALID_PARAMETER;
+  }
+
+  EcKey = EC_KEY_new_by_curve_name (Nid);
+  if (EcKey == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Ret = SSL_set_tmp_ecdh (TlsConn->Ssl, EcKey);
+  EC_KEY_free (EcKey);
+
+  if (Ret != 1) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+ #endif
+}
+
 /**
   Gets the protocol version used by the specified TLS connection.
 
@@ -1306,3 +1616,53 @@ TlsGetCertRevocationList (
 {
   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;
+}
diff --git a/CryptoPkg/Library/TlsLib/TlsProcess.c b/CryptoPkg/Library/TlsLib/TlsProcess.c
index 0f2ad7a9fb..a803d86c4f 100644
--- a/CryptoPkg/Library/TlsLib/TlsProcess.c
+++ b/CryptoPkg/Library/TlsLib/TlsProcess.c
@@ -461,3 +461,35 @@ TlsWrite (
   //
   return SSL_write (TlsConn->Ssl, Buffer, (UINT32)BufferSize);
 }
+
+/**
+  Shutdown a TLS connection.
+
+  Shutdown the TLS connection without releasing the resources, meaning a new
+  connection can be started without calling TlsNew() and without setting
+  certificates etc.
+
+  @param[in]       Tls            Pointer to the TLS object to shutdown.
+
+  @retval EFI_SUCCESS             The TLS is shutdown successfully.
+  @retval EFI_INVALID_PARAMETER   Tls is NULL.
+  @retval EFI_PROTOCOL_ERROR      Some other error occurred.
+**/
+EFI_STATUS
+EFIAPI
+TlsShutdown (
+  IN     VOID  *Tls
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *)Tls;
+
+  if ((TlsConn == NULL) || ((TlsConn->Ssl) == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  SSL_set_quiet_shutdown (TlsConn->Ssl, 1);
+  SSL_shutdown (TlsConn->Ssl);
+  return SSL_clear (TlsConn->Ssl) == 1 ? EFI_SUCCESS : EFI_PROTOCOL_ERROR;
+}
diff --git a/CryptoPkg/Library/TlsLibNull/TlsConfigNull.c b/CryptoPkg/Library/TlsLibNull/TlsConfigNull.c
index 03726fd726..18dd604382 100644
--- a/CryptoPkg/Library/TlsLibNull/TlsConfigNull.c
+++ b/CryptoPkg/Library/TlsLibNull/TlsConfigNull.c
@@ -242,11 +242,42 @@ TlsSetHostPublicCert (
 /**
   Adds the local private key to the specified TLS object.
 
-  This function adds the local private key (PEM-encoded RSA or PKCS#8 private
+  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 PEM-encoded RSA
+  @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
+  )
+{
+  ASSERT (FALSE);
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  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.
 
@@ -292,6 +323,61 @@ TlsSetCertRevocationList (
   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
+  )
+{
+  ASSERT (FALSE);
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  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
+  )
+{
+  ASSERT (FALSE);
+  return EFI_UNSUPPORTED;
+}
+
 /**
   Gets the protocol version used by the specified TLS connection.
 
@@ -617,3 +703,36 @@ TlsGetCertRevocationList (
   ASSERT (FALSE);
   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
+  )
+{
+  ASSERT (FALSE);
+  return EFI_UNSUPPORTED;
+}
diff --git a/CryptoPkg/Library/TlsLibNull/TlsProcessNull.c b/CryptoPkg/Library/TlsLibNull/TlsProcessNull.c
index 0958ddd8d6..395dac548d 100644
--- a/CryptoPkg/Library/TlsLibNull/TlsProcessNull.c
+++ b/CryptoPkg/Library/TlsLibNull/TlsProcessNull.c
@@ -245,3 +245,26 @@ TlsWrite (
   ASSERT (FALSE);
   return 0;
 }
+
+/**
+  Shutdown a TLS connection.
+
+  Shutdown the TLS connection without releasing the resources, meaning a new
+  connection can be started without calling TlsNew() and without setting
+  certificates etc.
+
+  @param[in]       Tls            Pointer to the TLS object to shutdown.
+
+  @retval EFI_SUCCESS             The TLS is shutdown successfully.
+  @retval EFI_INVALID_PARAMETER   Tls is NULL.
+  @retval EFI_PROTOCOL_ERROR      Some other error occurred.
+**/
+EFI_STATUS
+EFIAPI
+TlsShutdown (
+  IN     VOID  *Tls
+  )
+{
+  ASSERT (FALSE);
+  return EFI_UNSUPPORTED;
+}
-- 
2.31.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#94834): https://edk2.groups.io/g/devel/message/94834
Mute This Topic: https://groups.io/mt/94193505/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list