]> git.proxmox.com Git - mirror_edk2.git/blobdiff - CryptoPkg/Library/TlsLib/TlsInit.c
CryptoPkg: Add new TlsLib library
[mirror_edk2.git] / CryptoPkg / Library / TlsLib / TlsInit.c
diff --git a/CryptoPkg/Library/TlsLib/TlsInit.c b/CryptoPkg/Library/TlsLib/TlsInit.c
new file mode 100644 (file)
index 0000000..6b1fd93
--- /dev/null
@@ -0,0 +1,291 @@
+/** @file
+  SSL/TLS Initialization Library Wrapper Implementation over OpenSSL.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+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 "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.
+
+**/
+VOID
+EFIAPI
+TlsInitialize (
+  VOID
+  )
+{
+  //
+  // Performs initialization of crypto and ssl library, and loads required
+  // algorithms.
+  //
+  SSL_library_init ();
+
+  //
+  // Loads error strings from both crypto and ssl library.
+  //
+  SSL_load_error_strings ();
+
+  /// OpenSSL_add_all_algorithms();
+
+  //
+  // Initialize the pseudorandom number generator.
+  //
+  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.  Client can use higher
+  // TLS version if server supports it
+  //
+  switch (ProtoVersion) {
+  case TLS1_VERSION:
+    //
+    // TLS 1.0
+    //
+    break;
+  case TLS1_1_VERSION:
+    //
+    // TLS 1.1
+    //
+    SSL_CTX_set_options (TlsCtx, SSL_OP_NO_TLSv1);
+    break;
+  case TLS1_2_VERSION:
+    //
+    // TLS 1.2
+    //
+    SSL_CTX_set_options (TlsCtx, SSL_OP_NO_TLSv1);
+    SSL_CTX_set_options (TlsCtx, SSL_OP_NO_TLSv1_1);
+    break;
+  default:
+    //
+    // Unsupported TLS/SSL Protocol Version.
+    //
+    break;
+  }
+
+  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 BIO objects.
+  //
+  if (TlsConn->Ssl != NULL) {
+    SSL_free (TlsConn->Ssl);
+  }
+
+  if (TlsConn->InBio != NULL) {
+    BIO_free (TlsConn->InBio);
+  }
+
+  if (TlsConn->OutBio != NULL) {
+    BIO_free (TlsConn->OutBio);
+  }
+
+  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;
+  }
+
+  //
+  // 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;
+}