/** @file SSL/TLS Initialization Library Wrapper Implementation over OpenSSL. Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
(C) Copyright 2016 Hewlett Packard Enterprise Development LP
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "InternalTlsLib.h" /** Initializes the OpenSSL library. This function registers ciphers and digests used directly and indirectly by SSL/TLS, and initializes the readable error messages. This function must be called before any other action takes places. @retval TRUE The OpenSSL library has been initialized. @retval FALSE Failed to initialize the OpenSSL library. **/ BOOLEAN EFIAPI TlsInitialize ( VOID ) { INTN Ret; // // Performs initialization of crypto and ssl library, and loads required // algorithms. // Ret = OPENSSL_init_ssl ( OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL ); if (Ret != 1) { return FALSE; } // // Initialize the pseudorandom number generator. // return RandomSeed (NULL, 0); } /** Free an allocated SSL_CTX object. @param[in] TlsCtx Pointer to the SSL_CTX object to be released. **/ VOID EFIAPI TlsCtxFree ( IN VOID *TlsCtx ) { if (TlsCtx == NULL) { return; } if (TlsCtx != NULL) { SSL_CTX_free ((SSL_CTX *) (TlsCtx)); } } /** Creates a new SSL_CTX object as framework to establish TLS/SSL enabled connections. @param[in] MajorVer Major Version of TLS/SSL Protocol. @param[in] MinorVer Minor Version of TLS/SSL Protocol. @return Pointer to an allocated SSL_CTX object. If the creation failed, TlsCtxNew() returns NULL. **/ VOID * EFIAPI TlsCtxNew ( IN UINT8 MajorVer, IN UINT8 MinorVer ) { SSL_CTX *TlsCtx; UINT16 ProtoVersion; ProtoVersion = (MajorVer << 8) | MinorVer; TlsCtx = SSL_CTX_new (SSLv23_client_method ()); if (TlsCtx == NULL) { return NULL; } // // Ensure SSLv3 is disabled // SSL_CTX_set_options (TlsCtx, SSL_OP_NO_SSLv3); // // Treat as minimum accepted versions by setting the minimal bound. // Client can use higher TLS version if server supports it // SSL_CTX_set_min_proto_version (TlsCtx, ProtoVersion); return (VOID *) TlsCtx; } /** Free an allocated TLS object. This function removes the TLS object pointed to by Tls and frees up the allocated memory. If Tls is NULL, nothing is done. @param[in] Tls Pointer to the TLS object to be freed. **/ VOID EFIAPI TlsFree ( IN VOID *Tls ) { TLS_CONNECTION *TlsConn; TlsConn = (TLS_CONNECTION *) Tls; if (TlsConn == NULL) { return; } // // Free the internal TLS and related BIO objects. // if (TlsConn->Ssl != NULL) { SSL_free (TlsConn->Ssl); } OPENSSL_free (Tls); } /** Create a new TLS object for a connection. This function creates a new TLS object for a connection. The new object inherits the setting of the underlying context TlsCtx: connection method, options, verification setting. @param[in] TlsCtx Pointer to the SSL_CTX object. @return Pointer to an allocated SSL object. If the creation failed, TlsNew() returns NULL. **/ VOID * EFIAPI TlsNew ( IN VOID *TlsCtx ) { TLS_CONNECTION *TlsConn; SSL_CTX *SslCtx; X509_STORE *X509Store; TlsConn = NULL; // // Allocate one new TLS_CONNECTION object // TlsConn = (TLS_CONNECTION *) OPENSSL_malloc (sizeof (TLS_CONNECTION)); if (TlsConn == NULL) { return NULL; } TlsConn->Ssl = NULL; // // Create a new SSL Object // TlsConn->Ssl = SSL_new ((SSL_CTX *) TlsCtx); if (TlsConn->Ssl == NULL) { TlsFree ((VOID *) TlsConn); return NULL; } // // This retains compatibility with previous version of OpenSSL. // SSL_set_security_level (TlsConn->Ssl, 0); // // Initialize the created SSL Object // SSL_set_info_callback (TlsConn->Ssl, NULL); TlsConn->InBio = NULL; // // Set up Reading BIO for TLS connection // TlsConn->InBio = BIO_new (BIO_s_mem ()); if (TlsConn->InBio == NULL) { TlsFree ((VOID *) TlsConn); return NULL; } // // Sets the behaviour of memory BIO when it is empty. It will set the // read retry flag. // BIO_set_mem_eof_return (TlsConn->InBio, -1); TlsConn->OutBio = NULL; // // Set up Writing BIO for TLS connection // TlsConn->OutBio = BIO_new (BIO_s_mem ()); if (TlsConn->OutBio == NULL) { TlsFree ((VOID *) TlsConn); return NULL; } // // Sets the behaviour of memory BIO when it is empty. It will set the // write retry flag. // BIO_set_mem_eof_return (TlsConn->OutBio, -1); ASSERT (TlsConn->Ssl != NULL && TlsConn->InBio != NULL && TlsConn->OutBio != NULL); // // 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 // SslCtx = SSL_get_SSL_CTX (TlsConn->Ssl); X509Store = SSL_CTX_get_cert_store (SslCtx); if (X509Store == NULL) { X509Store = X509_STORE_new (); if (X509Store == NULL) { TlsFree ((VOID *) TlsConn); return NULL; } SSL_CTX_set1_verify_cert_store (SslCtx, 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 ); return (VOID *) TlsConn; }