/*!
 * \file      sha384.hh
 * \brief     Header file for SHA-384 helper methods.
 * \author    ETSI STF525
 * \copyright ETSI Copyright Notification
 *            No part may be reproduced except as authorized by written permission.
 *            The copyright and the foregoing restriction extend to reproduction in all media.
 *            All rights reserved.
 * \version   0.1
 */
#pragma once

#include <vector>

#include <openssl/sha.h>
#include <openssl/objects.h>

/*!
 * \class sha384
 * \brief  This class provides description of SHA-384 helper methods
 */
class sha384 {
  SHA512_CTX _ctx; //! SHA context
public: //! \publicsection
  /*!
   * \brief Default constructor
   *        Create a new instance of the sha384 class
   */
  explicit sha384(): _ctx{} { };
  /*!
   * \brief Default destructor
   */
  virtual ~sha384() { };

  /*!
   * \inline
   * \fn int generate(const std::vector<unsigned char> p_buffer, std::vector<unsigned char>& p_hash);
   * \brief Receive bytes formated data from the lower layers
   * \param[in] p_buffer The data used to generate the SHA-384 hash
   * \param[out] p_hash The SHA-384 hash value based of the provided data
   * \return 0 on success, -1 otherwise
   */
  inline int generate(const std::vector<unsigned char> p_buffer, std::vector<unsigned char>& p_hash) {
    // Sanity check
    /*if (p_buffer.size() == 0) {
      return -1;
      }*/

    return generate(p_buffer.data(), p_buffer.size(), p_hash);
  };
  
  /*!
   * \inline
   * \fn int generate(const std::vector<unsigned char> p_buffer, std::vector<unsigned char>& p_hash);
   * \brief Receive bytes formated data from the lower layers
   * \param[in] p_buffer The data used to generate the SHA-384 hash
   * \param[in] The length of the data buffer
   * \param[out] p_hash The SHA-384 hash value based of the provided data
   * \return 0 on success, -1 otherwise
   */
  inline int generate(const unsigned char *p_buffer, const size_t p_length, std::vector<unsigned char>& p_hash) {
    // Sanity check
    /*if (p_buffer == nullptr) {
      return -1;
      }*/
    // Resize data buffer
    p_hash.resize(SHA384_DIGEST_LENGTH);
    // Compute the hash value
    ::SHA384_Init(&_ctx);
    ::SHA384_Update(&_ctx, p_buffer, p_length);
    ::SHA384_Final(static_cast<unsigned char*>(p_hash.data()), &_ctx);
    return 0;
  };

  /*!
   * \inline
   * \fn const std::vector<unsigned char> get_sha384_empty_string() const;
   * \brief Return the SHA-384 of an empty string
   * \return The SHA-384 of an empty string
   */
  inline const std::vector<unsigned char> get_sha384_empty_string() {
    static unsigned char sha384_empty_string[] = { 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b }; //! SHA-384 of an empty string
    return std::vector<unsigned char>(sha384_empty_string, sha384_empty_string + 48);
  };
}; // End of class sha384
