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