This patch did following updates:
* Set X509_STORE Verify callback function to support "Live Certificate"
with the capacity of user trusted/untrusted hint popup if server CA
certificate received in handshake message.
* Refine the coding style.

Cc: Palmer Thomas <thomas.pal...@hpe.com>
Cc: Samer El-Haj-Mahmoud <smahm...@lenovo.com>
Cc: Long Qin <qin.l...@intel.com>
Cc: Ye Ting <ting...@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiaxin Wu <jiaxin...@intel.com>
---
 CryptoPkg/Library/TlsLib/TlsLib.c   | 200 +++++++++++++++++++++++++-----------
 CryptoPkg/Library/TlsLib/TlsLib.inf |   3 +-
 2 files changed, 144 insertions(+), 59 deletions(-)

diff --git a/CryptoPkg/Library/TlsLib/TlsLib.c 
b/CryptoPkg/Library/TlsLib/TlsLib.c
index 814c358..0a1cf03 100644
--- a/CryptoPkg/Library/TlsLib/TlsLib.c
+++ b/CryptoPkg/Library/TlsLib/TlsLib.c
@@ -10,11 +10,11 @@ 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 <Library/UefiLib.h>
 #include <Library/BaseCryptLib.h>
 
 #include <openssl/ssl.h>
 #include <openssl/bio.h>
 #include <openssl/err.h>
@@ -59,16 +59,49 @@ STATIC CONST TLS_CIPHER_PAIR TlsCipherMappingTable[] = {
   { 0x0005, "RC4-SHA" },              /// TLS_RSA_WITH_RC4_128_SHA
   { 0x0009, "DES-CBC-SHA" },          /// TLS_RSA_WITH_DES_CBC_SHA
   { 0x000A, "DES-CBC3-SHA" },         /// TLS_RSA_WITH_3DES_EDE_CBC_SHA
   { 0x002F, "AES128-SHA" },           /// TLS_RSA_WITH_AES_128_CBC_SHA
   { 0x0035, "AES256-SHA" },           /// TLS_RSA_WITH_AES_256_CBC_SHA
-  { 0x003B, "NULL-SHA256" },          /// TLS_RSA_WITH_NULL_SHA256
+  { 0x003B, "NULL-SHA256" },          /// TLS_RSA_WITH_NULL_SHA256
   { 0x003C, "AES128-SHA256" },        /// TLS_RSA_WITH_AES_128_CBC_SHA256
   { 0x003D, "AES256-SHA256" }         /// TLS_RSA_WITH_AES_256_CBC_SHA256
 };
 
 /**
+  Get Ack infor from the popup window.
+
+  @param[in]       String    Point to showed string buffer.
+  
+**/
+UINT8
+PopupAckWindow (
+  IN     CHAR16      *String
+  )
+{
+  EFI_INPUT_KEY Key;
+  UINT8         Ret;
+
+  Ret = 0;
+
+  CreatePopUp (
+    EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+    &Key,
+    String,
+    L"Press 'Y' to trust it, or else the session will be interrupted!",
+    NULL
+    );
+  
+  if (Key.UnicodeChar == 'y' || Key.UnicodeChar == 'Y') {
+    Ret = 1;
+  } else {
+    Ret = 0;
+  }
+
+  return Ret;
+}
+
+/**
   Gets the OpenSSL cipher suite string for the supplied IANA TLS cipher suite.
 
   @param[in]  CipherId    The supplied IANA TLS cipher suite ID.
 
   @return  The corresponding OpenSSL cipher suite string if found,
@@ -104,10 +137,42 @@ TlsGetCipherString (
   // No Cipher Mapping found, return NULL.
   //
   return NULL;
 }
 
+STATIC
+INT32
+TlsVerifyCallback (
+  INT32           ok, 
+  X509_STORE_CTX  *ctx
+  )
+{
+  INT32  Err;
+
+  INT32  Ret;
+
+  Ret = 0;
+
+  if (!ok) {
+    //
+    // X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN means the certificate chain could 
be built up 
+    // using the untrusted certificates but the root could not be found 
locally. 
+    // Detailed descriptions see 
https://www.openssl.org/docs/manmaster/apps/verify.html.
+    //
+    Err = X509_STORE_CTX_get_error(ctx);
+    if (Err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
+      Ret = PopupAckWindow (L"Trust the remote root certificate?");
+
+      //gST->ConOut->ClearScreen (gST->ConOut);
+      
+      return Ret;
+    }
+  }
+
+  return ok;
+}
+
 /**
   Initializes the OpenSSL library.
 
   This function registers ciphers and digests used directly and indirectly
   by SSL/TLS, and initializes the readable error messages.
@@ -128,11 +193,11 @@ TlsInitialize (
 
   //
   // Loads error strings from both crypto and ssl library.
   //
   SSL_load_error_strings ();
-
+
   /// OpenSSL_add_all_algorithms();
 
   //
   // Initialize the pseudorandom number generator.
   //
@@ -272,11 +337,11 @@ EFIAPI
 TlsNew (
   IN     VOID                     *TlsCtx
   )
 {
   TLS_CONNECTION  *TlsConn;
-  X509_STORE      *X509Store;
+  X509_STORE      *X509Store;
 
   TlsConn = NULL;
 
   //
   // Allocate one new TLS_CONNECTION object
@@ -341,32 +406,41 @@ TlsNew (
   //
   // Connects the InBio and OutBio for the read and write operations.
   //
   SSL_set_bio (TlsConn->Ssl, TlsConn->InBio, TlsConn->OutBio);
 
-
-  //
-  // Create new X509 store if needed
-  //
-  X509Store = SSL_CTX_get_cert_store (TlsConn->Ssl->ctx);
-  if (X509Store == NULL) {
-    X509Store = X509_STORE_new ();
-    if (X509Store == NULL) {
-      TlsFree ((VOID *) TlsConn);
-      return NULL;
-    }
-    SSL_CTX_set1_verify_cert_store (TlsConn->Ssl->ctx, X509Store);
-    X509_STORE_free (X509Store);
-  }
-
-  //
-  // Set X509_STORE flags used in certificate validation
-  //
-  X509_STORE_set_flags (
-    X509Store,
-    X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME
-    );
+
+  //
+  // Create new X509 store if needed
+  //
+  X509Store = SSL_CTX_get_cert_store (TlsConn->Ssl->ctx);
+  if (X509Store == NULL) {
+    X509Store = X509_STORE_new ();
+    if (X509Store == NULL) {
+      TlsFree ((VOID *) TlsConn);
+      return NULL;
+    }
+    SSL_CTX_set1_verify_cert_store (TlsConn->Ssl->ctx, X509Store);
+    X509_STORE_free (X509Store);
+  }
+
+  //
+  // Set X509_STORE flags used in certificate validation
+  //
+  X509_STORE_set_flags (
+    X509Store,
+    X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME
+    );
+
+  //
+  // Set X509_STORE Verify callback function
+  //
+  X509_STORE_set_verify_cb (
+    X509Store, 
+    TlsVerifyCallback
+    );
+  
   return (VOID *) TlsConn;
 }
 
 /**
   Checks if the TLS handshake was done.
@@ -614,70 +688,80 @@ TlsDoHandshake (
   IN OUT UINTN                    *BufferOutSize
   )
 {
   TLS_CONNECTION  *TlsConn;
   UINTN           PendingBufferSize;
-  int             ret;
-  unsigned long   e;
+  INTN            Ret;
+  unsigned long   ErrorCode;
 
   TlsConn           = (TLS_CONNECTION *) Tls;
   PendingBufferSize = 0;
+  Ret               = 1;
 
   if (TlsConn == NULL || \
     TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL 
|| \
     BufferOutSize == NULL || \
     (BufferIn == NULL && BufferInSize != 0) || \
     (BufferIn != NULL && BufferInSize == 0) || \
     (BufferOut == NULL && *BufferOutSize != 0)) {
     return EFI_INVALID_PARAMETER;
   }
   
-  ret = 1;
   if(BufferIn == NULL && BufferInSize == 0) {
     //
     // If RequestBuffer is NULL and RequestSize is 0, and TLS session 
     // status is EfiTlsSessionNotStarted, the TLS session will be initiated 
     // and the response packet needs to be ClientHello.
     //
     PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
     if (PendingBufferSize == 0) {
       SSL_set_connect_state (TlsConn->Ssl);
-      ret = SSL_do_handshake (TlsConn->Ssl);
+      Ret = SSL_do_handshake (TlsConn->Ssl);
       PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
     }
   } else {
     PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
     if (PendingBufferSize == 0) {
       BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize);
-      ret = SSL_do_handshake (TlsConn->Ssl);
+      Ret = SSL_do_handshake (TlsConn->Ssl);
       PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
     }
   }
 
-  if (ret < 1) {
-    ret = SSL_get_error (TlsConn->Ssl, ret);
-    if (ret == SSL_ERROR_SSL ||
-        ret == SSL_ERROR_SYSCALL ||
-        ret == SSL_ERROR_ZERO_RETURN) {
-      DEBUG ((DEBUG_ERROR, "%a SSL_HANDSHAKE_ERROR State=0x%x SSL_ERROR_%a\n", 
__FUNCTION__, SSL_state (TlsConn->Ssl),
-            ret == SSL_ERROR_SSL ? "SSL":
-            ret == SSL_ERROR_SYSCALL ? "SYSCALL":
-            "ZERO_RETURN"
-            ));
-      DEBUG_CODE_BEGIN ();
-      while (1) {
-        e = ERR_get_error ();
-        if (e == 0) {
-          break;
-        }
-        DEBUG ((DEBUG_ERROR, "%a ERROR 0x%x=L%x:F%x:R%x\n", __FUNCTION__, e, 
ERR_GET_LIB (e), ERR_GET_FUNC (e), ERR_GET_REASON (e)));
-      }
-      DEBUG_CODE_END ();
-      return EFI_PROTOCOL_ERROR;
-    }
-  }
-
+  if (Ret < 1) {
+    Ret = SSL_get_error (TlsConn->Ssl, Ret);
+    if (Ret == SSL_ERROR_SSL ||
+        Ret == SSL_ERROR_SYSCALL ||
+        Ret == SSL_ERROR_ZERO_RETURN) {
+      DEBUG ((
+        DEBUG_ERROR, 
+        "%a SSL_HANDSHAKE_ERROR State=0x%x SSL_ERROR_%a\n",
+        __FUNCTION__, 
+        SSL_state (TlsConn->Ssl),
+        Ret == SSL_ERROR_SSL ? "SSL" : Ret == SSL_ERROR_SYSCALL ? "SYSCALL" : 
"ZERO_RETURN"
+        ));
+      DEBUG_CODE_BEGIN ();
+        while (TRUE) {
+          ErrorCode = ERR_get_error ();
+          if (ErrorCode == 0) {
+            break;
+          }
+          DEBUG ((
+            DEBUG_ERROR, 
+            "%a ERROR 0x%x=L%x:F%x:R%x\n",
+            __FUNCTION__, 
+            ErrorCode, 
+            ERR_GET_LIB (ErrorCode), 
+            ERR_GET_FUNC (ErrorCode), 
+            ERR_GET_REASON (ErrorCode)
+            ));
+        }
+      DEBUG_CODE_END ();
+      return EFI_PROTOCOL_ERROR;
+    }
+  }
+
   if (PendingBufferSize > *BufferOutSize) {
     *BufferOutSize = PendingBufferSize;
     return EFI_BUFFER_TOO_SMALL;
   }
 
@@ -1524,13 +1608,13 @@ TlsSetCaCertificate (
   if (X509Store == NULL) {
       Status = EFI_ABORTED;
       goto ON_EXIT;
   }
 
-  //
-  // Add certificate to X509 store
-  //
+  //
+  // Add certificate to X509 store
+  //
   Ret = X509_STORE_add_cert (X509Store, Cert);
   if (Ret != 1) {
     ErrorCode = ERR_peek_last_error ();
     //
     // Ignore "already in table" errors
@@ -1539,11 +1623,11 @@ TlsSetCaCertificate (
         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);
   }
 
diff --git a/CryptoPkg/Library/TlsLib/TlsLib.inf 
b/CryptoPkg/Library/TlsLib/TlsLib.inf
index 6194e95..41f7ce0 100644
--- a/CryptoPkg/Library/TlsLib/TlsLib.inf
+++ b/CryptoPkg/Library/TlsLib/TlsLib.inf
@@ -41,6 +41,7 @@
   UefiRuntimeServicesTableLib
   DebugLib
   OpensslLib
   IntrinsicLib
   PrintLib
-  OpensslTlsLib
\ No newline at end of file
+  OpensslTlsLib
+  UefiLib
\ No newline at end of file
-- 
1.9.5.msysgit.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to