/** @file
  SSL/TLS Initialization Library Wrapper Implementation over OpenSSL.

Copyright (c) 2016 - 2017, 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.

  @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;
}

