Commit 59ef1904 authored by YannGarcia's avatar YannGarcia
Browse files

Bug fixed in signature check

parent 05b0d924
Loading
Loading
Loading
Loading
+61 −1
Original line number Diff line number Diff line
#include "LibHelpers_Functions.hh"
#include <math.h>
#include <sstream>
#include <iomanip>
#include <random>

#include "LibHelpers_Functions.hh"

#include "base_time.hh"
#include "converter.hh"
#include "loggers.hh"
#include "xml_converters.hh"

#ifndef M_PI
#define M_PI 3.14159265358979323846
@@ -74,4 +79,59 @@ namespace LibHelpers__Functions {
    return os;
  }

  static unsigned char random_char() {
    std::random_device rd;
    std::mt19937 gen(rd()); 
    std::uniform_int_distribution<> dis(0, 255);
    return static_cast<unsigned char>(dis(gen));
  }

  static std::string generate_hex(const unsigned int len) {
    std::stringstream ss;
    for(auto i = 0; i < len; i++) {
      auto rc = random_char();
      std::stringstream hexstream;
      hexstream << std::hex << int(rc);
      auto hex = hexstream.str(); 
      ss << (hex.length() < 2 ? '0' + hex : hex);
    }    
    return ss.str();
  }

  /**
   * @brief Generate a new UUID
   * @return The UUID in string format on success, a null string otherwise 
   */
  CHARSTRING fx__generate__uuid() { // ddb848c4-f7fd-445f-bdc8-033d15d7c528
    loggers::get_instance().log(">>> fx__generate__uuid");

    std::stringstream ss;
    ss << generate_hex(6) << "-";
    ss << generate_hex(2) << "-";
    ss << generate_hex(2) << "-";
    ss << generate_hex(2) << "-";
    ss << generate_hex(6);

    CHARSTRING uuid(ss.str().c_str());
    loggers::get_instance().log_msg("fx__generate__uuid: ", uuid);
    return uuid;
  }

  /**
   * @brief Retrieve the current local date/time formatted as yyyy-mm-ddThh:mm:ss.lll+nn:00
   * @return The the current date/time on success, a null string otherwise 
   */
  CHARSTRING fx__get__current__date__time() { //2018-01-18T13:19:35.367+01:00
    loggers::get_instance().log(">>> fx__get__current__date__time");

    time_t t = std::time(nullptr);
    auto tm = *std::localtime(&t);
    std::ostringstream oss;
    oss << std::put_time(&tm, "%FT%T");//%FT%T%Z

    CHARSTRING dt(oss.str().c_str());
    loggers::get_instance().log_msg("fx__get__current__date__time: ", dt);
    return dt;
  }

} // namespace LibHelpers__Functions
+1 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ public:

public:
  int xml_canonicalization(const std::string& p_to_canonical, std::string& p_canonicalized) const;
  int xml_transform(const std::string& p_to_transform, std::string& p_transformed) const;

}; // End of class xml_converters

+69 −3
Original line number Diff line number Diff line
@@ -14,9 +14,77 @@

#include <libxml/parser.h>
#include <libxml/c14n.h>
#include <libxml/xpath.h>
#include <libxml/tree.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>

xml_converters* xml_converters::_instance = nullptr;

// FIXME Use libxslt
int xml_converters::xml_transform(const std::string& p_to_transform, std::string& p_transformed) const {
  loggers::get_instance().log(">>> xml_converters::xml_transform: '%s'", p_to_transform.c_str());


  xmlDocPtr doc = xmlReadMemory(p_to_transform.c_str(), p_to_transform.length(), "noname.xml", NULL, 0);
  xmlChar *xmlbuff;
  int buffersize;
  xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
  loggers::get_instance().log("xml_converters::xml_transform: tree dump: '%s'", (char *) xmlbuff);
  //"\\n\\t<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:s=\"http://www.w3.org/2000/09/xmldsig#\">\\n\\t\\t<xsl:strip-space elements=\"*\"/>\\n\\t\\t<xsl:output indent=\"false\" method=\"xml\" omit-xml-declaration=\"yes\"/>\\n\\t\\t\\t<xsl:template match=\"*[not(self::s:Signature)]\">\\n\\t\\t\\t<xsl:element name=\"{local-name()}\">\\n\\t\\t\\t<xsl:apply-templates select=\"*|text()\"/>\\n\\t\\t</xsl:element></xsl:template><xsl:template match=\"s:Signature\"/>\\n\\t</xsl:stylesheet>\\n\\t"
  
  //xsltApplyStylesheet(cur, doc, params);
  xmlFree(xmlbuff);
  xmlFreeDoc(doc);


  int first = p_to_transform.find('>');
  int next = 0;
  while ((first != -1) && (first < p_to_transform.length())) {
    //loggers::get_instance().log("xml_converters::xml_transform: first: '%d'", first);
    //loggers::get_instance().log("xml_converters::xml_transform: next: '%d'", next);
    p_transformed += p_to_transform.substr(next, first - next + 1);
    //loggers::get_instance().log("xml_converters::xml_transform: p_to_transform: '%s'", p_to_transform.c_str());
    //loggers::get_instance().log("xml_converters::xml_transform: p_transformed: '%s'", p_transformed.c_str());
    next = first + 1;
    while (
      (p_to_transform[next] == '\r') || 
      (p_to_transform[next] == '\n') || 
      (p_to_transform[next] == '\t') || 
      (p_to_transform[next] == ' ')
    ) { // Skip CR, LF, TAG and SPACE
      next += 1;
    } // End of 'while'statement
    first = p_to_transform.find('>', next);
  } // End of 'while'statement

  //<ns4:PullRequest xmlns:ns4="http://www.cise.eu/servicemodel/v1/message/">
  first = p_transformed.find("ns4:");
  while ((first != -1) && (first < p_to_transform.length())) {
    p_transformed = p_transformed.substr(0, first) + p_transformed.substr(first + 4,  p_transformed.length() - 4 - 1);
    loggers::get_instance().log("xml_converters::xml_transform: New p_transformed (1): '%s'", p_transformed.c_str());
    first = p_transformed.find("ns4:");
  } // End of 'while'statement

  first = p_transformed.find("xmlns:ns4");
  while ((first != -1) && (first < p_to_transform.length())) {
    next = p_transformed.find("\">", first + 1);
    p_transformed = p_transformed.substr(0, first - 1) + p_transformed.substr(next + 1,  p_transformed.length() - next - 1);
    loggers::get_instance().log("xml_converters::xml_transform: New p_transformed (2): '%s'", p_transformed.c_str());
    first = p_transformed.find("xmlns:ns4");
  } // End of 'while'statement

  // <Payload xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="XmlEntityPayload">
  first = p_transformed.find("<Payload");
  if ((first != -1) && (first < p_to_transform.length())) {
    next = p_transformed.find("\">", first + 8 + 1);
    p_transformed = p_transformed.substr(0, first + 8) + p_transformed.substr(next + 1,  p_transformed.length() - next - 1);
  }
  
  loggers::get_instance().log("<<< xml_converters::xml_transform: '%s'", p_transformed.c_str());
  return 0;
}

int xml_converters::xml_canonicalization(const std::string& p_to_canonical, std::string& p_canonicalized) const {
  loggers::get_instance().log(">>> xml_converters::xml_canonicalization: '%s'", p_to_canonical.c_str());

@@ -34,14 +102,12 @@ int xml_converters::xml_canonicalization(const std::string& p_to_canonical, std:
  }

  // Do canonicalization
  loggers::get_instance().log("xml_converters::xml_canonicalization: Before");
  if (xmlC14NExecute(doc, (xmlC14NIsVisibleCallback)&xml_converters::xml_node_set_contains_callback, nullptr, XML_C14N_1_1, nullptr, 1, buffer) == -1) {
  if (xmlC14NExecute(doc, nullptr/*(xmlC14NIsVisibleCallback)&xml_converters::xml_node_set_contains_callback*/, nullptr,  XML_C14N_EXCLUSIVE_1_0, nullptr, 1, buffer) == -1) {
    loggers::get_instance().log("xml_converters::xml_canonicalization: Failed to read XML input");
    xmlFreeDoc(doc);
    xmlOutputBufferClose(buffer);
    return -1;
  }
  loggers::get_instance().log("xml_converters::xml_canonicalization: After");

  // Retrieve the canonicalization XML document
  const char* data = (const char*)xmlOutputBufferGetContent(buffer);
+2 −2
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ public: /*! \publicsection */
   * \param[in] TODO The raw message to be signed
   * \return 0 on success, -1 otherwise
   */
  int do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_canonicalized);
  int do_sign(const OCTETSTRING& p_encoded_message, const OCTETSTRING& p_empty_signature, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_canonicalized);
  /*!
   * \fn int build_path(const std::string& p_root_directory);
   * \brief Verify message signature
@@ -56,5 +56,5 @@ public: /*! \publicsection */
   * \param[in] TODO
   * \return true on success, false otherwise
   */
  bool do_sign_verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate, const CHARSTRING& p_debug_message);
  bool do_sign_verify(const CHARSTRING& p_message, const OCTETSTRING& p_empty_signature, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate, CHARSTRING& p_debug_message);
};
 No newline at end of file
+124 −5
Original line number Diff line number Diff line
@@ -12,6 +12,66 @@

static std::unique_ptr<security_services> _security_services;

static int transform_signature_workaround(std::string& str) {
  loggers::get_instance().log(">>> transform_signature_workaround: '%s'", str.c_str());
  int first = str.find("&lt;");
  while ((first != -1) && (first < str.length())) {
    str = str.substr(0, first) + "<" + str.substr(first + 4,  str.length() - 4);
    //loggers::get_instance().log("transform_signature_workaround: New str (1): '%s'", str.c_str());
    first = str.find("&lt;");
  } // End of 'while'statement
  first = str.find("&gt;");
  while ((first != -1) && (first < str.length())) {
    str = str.substr(0, first) + ">" + str.substr(first + 4,  str.length() - 4);
    //loggers::get_instance().log("transform_signature_workaround: New str (2): '%s'", str.c_str());
    first = str.find("&gt;");
  } // End of 'while'statement
  first = str.find("&quot;");
  while ((first != -1) && (first < str.length())) {
    str = str.substr(0, first) + "'" + str.substr(first + 6,  str.length() - 6);
    //loggers::get_instance().log("transform_signature_workaround: New str (3): '%s'", str.c_str());
    first = str.find("&quot;");
  } // End of 'while'statement

  std::replace(str.begin(), str.end(), '\'', '\"');

  loggers::get_instance().log("<<< transform_signature_workaround: '%s'", str.c_str());
  return 0;
}

static int transform_xslt_workaround(std::string& str) {
  loggers::get_instance().log(">>> transform_xslt_workaround: '%s'", str.c_str());

  int start = str.find("<xsl:stylesheet");
  //loggers::get_instance().log("transform_xslt_workaround: start='%d' ", start);
  int stop = str.find("</Transform>");
  //loggers::get_instance().log("transform_xslt_workaround: stop='%d' ", stop);
  int first = str.find("<", start);
  while ((first != -1) && (first < stop)) {
    //loggers::get_instance().log("transform_xslt_workaround: first='%d' ", first);
    str = str.substr(0, first - 1) + "&lt;" + str.substr(first + 1,  str.length() - 1);
    //loggers::get_instance().log("transform_xslt_workaround: New str (1): '%s'", str.c_str());
    first = str.find("<", first);
  } // End of 'while'statement
  first = str.find(">", start);
  while ((first != -1) && (first < stop)) {
    //loggers::get_instance().log("transform_xslt_workaround: first='%d' ", first);
    str = str.substr(0, first - 1) + "&gt;" + str.substr(first + 1,  str.length() - 1);
    //loggers::get_instance().log("transform_xslt_workaround: New str (1): '%s'", str.c_str());
    first = str.find(">", first);
  } // End of 'while'statement
  first = str.find("\"", start);
  while ((first != -1) && (first < stop)) {
    //loggers::get_instance().log("transform_xslt_workaround: first='%d' ", first);
    str = str.substr(0, first - 1) + "&quot;" + str.substr(first + 1,  str.length() - 1);
    //loggers::get_instance().log("transform_xslt_workaround: New str (1): '%s'", str.c_str());
    first = str.find("\"", first);
  } // End of 'while'statement

  loggers::get_instance().log("<<< transform_xslt_workaround: '%s'", str.c_str());
  return 0;
}

INTEGER LibSecurity__Certificates::fx__init__certs__db(const CHARSTRING& p_certs_db_path) {
  loggers::get_instance().log_msg(">>> fx__init__certs__db: ", p_certs_db_path);

@@ -69,10 +129,70 @@ OCTETSTRING LibSecurity__Hash::fx__hash(const OCTETSTRING& p_to_be_hashed, const
  return hash;
}

INTEGER LibSecurity__Signature::fx__sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_canonicalized) {
OCTETSTRING LibSecurity__Signature::fx__enc__xmldsig__signed__info(const http__www__w3__org__2000__09__xmldsig::Signature_signedInfo& s) { // FIXME Use enc/dec TITAN function external function f_enc_value(in Value x) return bitstring with { extension "prototype(convert) encode(abc)" }
  loggers::get_instance().log(">>> fx__enc__xmldsig__signed__info");

  TTCN_EncDec::clear_error();
  TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);
  TTCN_Buffer encoding_buffer;

  s.encode(http__www__w3__org__2000__09__xmldsig::Signature_signedInfo_descr_, encoding_buffer, TTCN_EncDec::CT_XER, XER_EXTENDED);

  // FIXME Update <transform>
  std::string str(static_cast<const char*>((const char*)encoding_buffer.get_data()), encoding_buffer.get_len() + static_cast<const char*>((const char*)encoding_buffer.get_data()));
  loggers::get_instance().log("fx__enc__xmldsig__signed__info: Before str: '%s'", str.c_str());
  transform_signature_workaround(str);
  loggers::get_instance().log("fx__enc__xmldsig__signed__info: Afer str: '%s'", str.c_str());

  OCTETSTRING os = char2oct(CHARSTRING(str.c_str()));
  loggers::get_instance().log_msg("fx__enc__xmldsig__signed__info: os: ", os);

  return os;
}

OCTETSTRING LibSecurity__Signature::fx__enc__xmldsig(const http__www__w3__org__2000__09__xmldsig::Signature& s) { // FIXME Use enc/dec TITAN function external function f_enc_value(in Value x) return bitstring with { extension "prototype(convert) encode(abc)" }
  loggers::get_instance().log(">>> fx__enc__xmldsig");

  TTCN_EncDec::clear_error();
  TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);
  TTCN_Buffer encoding_buffer;

  s.encode(http__www__w3__org__2000__09__xmldsig::Signature_descr_, encoding_buffer, TTCN_EncDec::CT_XER, XER_EXTENDED);

  // FIXME Update <transform>
  std::string str(static_cast<const char*>((const char*)encoding_buffer.get_data()), encoding_buffer.get_len() + static_cast<const char*>((const char*)encoding_buffer.get_data()));
  loggers::get_instance().log("fx__enc__xmldsig: Before str: '%s'", str.c_str());
  transform_signature_workaround(str);
  loggers::get_instance().log("fx__enc__xmldsig: Afer str: '%s'", str.c_str());

  OCTETSTRING os = char2oct(CHARSTRING(str.c_str()));
  loggers::get_instance().log_msg("fx__enc__xmldsig: os: ", os);

  return os;
}

INTEGER LibSecurity__Signature::fx__dec__xmldsig(const BITSTRING& bs, http__www__w3__org__2000__09__xmldsig::Signature& s) { // FIXME Use enc/dec TITAN function external function f_enc_value(in Value x) return bitstring with { extension "prototype(convert) encode(abc)" }
  loggers::get_instance().log(">>> fx__dec__xmldsig");

  std::string str(static_cast<const char*>(oct2char(bit2oct(bs))));
  loggers::get_instance().log("fx__dec__xmldsig: Before str: '%s'", str.c_str());
  transform_xslt_workaround(str);
  loggers::get_instance().log("fx__dec__xmldsig: Afer str: '%s'", str.c_str());

  TTCN_EncDec::clear_error();
  TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);
  TTCN_Buffer decoding_buffer(OCTETSTRING(str.length(), (const unsigned char*)str.c_str()));

  s.decode(http__www__w3__org__2000__09__xmldsig::Signature_descr_, decoding_buffer, TTCN_EncDec::CT_XER, XER_EXTENDED);

  loggers::get_instance().log_msg("<<< fx__dec__xmldsig: ", s);
  return 0;
}

INTEGER LibSecurity__Signature::fx__sign(const OCTETSTRING& p_encoded_message, const OCTETSTRING& p_empty_signature, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_canonicalized) {
  loggers::get_instance().log_msg(">>> fx__sign: ", p_encoded_message);

  if (_security_services->do_sign(p_encoded_message, p_certificate_name, p_private_key_name, p_private_key_passwd, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem, p_pull_request_canonicalized) == -1) {
  if (_security_services->do_sign(p_encoded_message, p_empty_signature, p_certificate_name, p_private_key_name, p_private_key_passwd, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem, p_pull_request_canonicalized) == -1) {
    loggers::get_instance().log("fx__sign: Failed to signed message");
    return -1;
  }
@@ -80,14 +200,13 @@ INTEGER LibSecurity__Signature::fx__sign(const OCTETSTRING& p_encoded_message, c
  return 0;
}

BOOLEAN LibSecurity__Signature::fx__do__sign__verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate, const CHARSTRING& p_debug_message) {
BOOLEAN LibSecurity__Signature::fx__do__sign__verify(const CHARSTRING& p_message, const OCTETSTRING& p_empty_signature, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate, CHARSTRING& p_debug_message) {
  loggers::get_instance().log(">>> fx__do__sign__verify");

  if (!_security_services->do_sign_verify(p_message, p_canonicalization_method, p_signature_method, p_digest_method, p_digest_value, p_signature_value, p_subject_name, p_certificate, p_debug_message)) {
  if (!_security_services->do_sign_verify(p_message, p_empty_signature, p_canonicalization_method, p_signature_method, p_digest_method, p_digest_value, p_signature_value, p_subject_name, p_certificate, p_debug_message)) {
    loggers::get_instance().log("fx__do__sign__verify: Failed to verify message signature");
    return false;
  }
  
  return true;
}
  
 No newline at end of file
Loading