示例#1
0
   ~Application()
      {
      U_TRACE(5, "Application::~Application()")

      U_SYSCALL_VOID_NO_PARAM(xmlCleanupParser);
      U_SYSCALL_VOID_NO_PARAM(xmlMemoryDump);
      }
示例#2
0
文件: dbi.cpp 项目: psfu/ULib
UDBI::~UDBI()
{
   U_TRACE_UNREGISTER_OBJECT(0, UDBI)

   close();

#if LIBDBI_LIB_CURRENT <= 1
   U_SYSCALL_VOID_NO_PARAM(dbi_shutdown);
#else
   U_SYSCALL_VOID(dbi_shutdown_r, "%p", pinst);
#endif
}
示例#3
0
文件: thread.cpp 项目: paul-nema/ULib
void UThread::yield()
{
   U_TRACE_NO_PARAM(1, "UThread::yield()")

   // Yields the current thread's CPU time slice to allow another thread to begin immediate execution

   U_INTERNAL_DUMP("cancel = %d", cancel)

#ifdef HAVE_PTHREAD_CANCEL
   U_SYSCALL_VOID_NO_PARAM(pthread_testcancel);
#elif !defined(_MSWINDOWS_) && !defined(__UNIKERNEL__)
   sigset_t old = 0;

   if (cancel != cancelInitial &&
       cancel != cancelDisabled)
      {
      sigset_t scancel;

#  ifdef sigemptyset
                       sigemptyset(&scancel);
#  else
      (void) U_SYSCALL(sigemptyset, "%p", &scancel);
#  endif

#  ifdef sigaddset
                       sigaddset(&scancel, U_SIG_THREAD_CANCEL);
#  else
      (void) U_SYSCALL(sigaddset, "%p,%d", &scancel, U_SIG_THREAD_CANCEL);
#  endif

      (void) U_SYSCALL(pthread_sigmask, "%d,%p,%p", SIG_UNBLOCK, &scancel, &old);
      }
#endif

#ifdef HAVE_PTHREAD_YIELD
   (void) U_SYSCALL_NO_PARAM(pthread_yield);
#endif

#if !defined(HAVE_PTHREAD_CANCEL) && !defined(_MSWINDOWS_) && !defined(__UNIKERNEL__)
   if (old) (void) U_SYSCALL(pthread_sigmask, "%d,%p,%p", SIG_SETMASK, &old, 0);
#endif
}
示例#4
0
文件: archive.cpp 项目: fast01/ULib
   void run(int argc, char* argv[], char* env[])
      {
      U_TRACE(5, "Application::run(%d,%p,%p)", argc, argv, env)

      UApplication::run(argc, argv, env);

      U_SYSCALL_VOID_NO_PARAM(xmlInitParser); // init libxml

      LIBXML_TEST_VERSION

      // manage options

      num_args = (argc - optind);

      U_INTERNAL_DUMP("optind = %d num_args = %d", optind, num_args)

      if (UApplication::isOptions()) cfg_str = opt['c'];

      // manage file configuration

      if (cfg_str.empty()) cfg_str = U_STRING_FROM_CONSTANT("XAdES.ini");

      // ----------------------------------------------------------------------------------------------------------------------------------
      // XAdES signature - configuration parameters
      // ----------------------------------------------------------------------------------------------------------------------------------
      // DigestAlgorithm   md2 | md5 | sha | sha1 | sha224 | sha256 | sha384 | sha512 | mdc2 | ripmed160
      //
      // SigningTime this property contains the time at which the signer claims to have performed the signing process (yes/no)
      // ClaimedRole this property contains claimed or certified roles assumed by the signer in creating the signature
      //
      // this property contains the indication of the purported place where the signer claims to have produced the signature
      // -------------------------------------------------------------------------------------------------------------------
      // ProductionPlaceCity
      // ProductionPlaceStateOrProvince
      // ProductionPlacePostalCode
      // ProductionPlaceCountryName
      // -------------------------------------------------------------------------------------------------------------------
      //
      // DataObjectFormatMimeType   this property identifies the format of a signed data object (when electronic signatures
      //                            are not exchanged in a restricted context) to enable the presentation to the verifier or
      //                            use by the verifier (text, sound or video) in exactly the same way as intended by the signer
      //
      // CAStore
      // ArchiveTimeStamp           the time-stamp token within this property covers the archive validation data
      //
      // SignatureTimeStamp         the time-stamp token within this property covers the digital signature value element
      // Schema                     the pathname XML Schema of XAdES
      // ----------------------------------------------------------------------------------------------------------------------------------

      cfg.UFile::setPath(cfg_str);

      UString x(U_CAPACITY);

      UServices::readEOF(STDIN_FILENO, x);

      if (x.empty()) U_ERROR("cannot read data from <stdin>");

      content.setBuffer(x.size());

      UBase64::decode(x, content);

      if (content.empty()) U_ERROR("decoding data read failed");

      // manage arguments...

      archive_timestamp = ( U_ARCHIVE_TIMESTAMP == 0 ||
                           *U_ARCHIVE_TIMESTAMP == '\0'
                              ? cfg[U_STRING_FROM_CONSTANT("XAdES-L.ArchiveTimeStamp")]
                              : UString(U_ARCHIVE_TIMESTAMP));

      if (archive_timestamp.empty()) U_ERROR("error on archive timestamp: empty");

      schema = ( U_SCHEMA == 0 ||
                *U_SCHEMA == '\0'
                  ? cfg[U_STRING_FROM_CONSTANT("XAdES-L.Schema")]
                  : UString(U_SCHEMA));

      if (schema.empty()) U_ERROR("error on XAdES schema: empty");

      UXML2Schema XAdES_schema(UFile::contentOf(schema));

      // ---------------------------------------------------------------------------------------------------------------
      // check for OOffice or MS-Word document...
      // ---------------------------------------------------------------------------------------------------------------
      utility.handlerConfig(cfg);

      if (utility.checkDocument(content, "XAdES-C", false)) content = utility.getSigned();
      // ---------------------------------------------------------------------------------------------------------------

      UXML2Document document(content);

      if (XAdES_schema.validate(document) == false) U_ERROR("error on input data: not XAdES");

      // manage arguments...

      /*
      The input to the computation of the digest value MUST be built as follows:

      1) Initialize the final octet stream as an empty octet stream.

      2) Take all the ds:Reference elements in their order of appearance within ds:SignedInfo referencing
         whatever the signer wants to sign including the SignedProperties element. Process each one as indicated below:

         - Process the retrieved ds:Reference element according to the reference processing model of XMLDSIG.

         - If the result is a XML node set, canonicalize it. If ds:Canonicalization is present, the algorithm
           indicated by this element is used. If not, the standard canonicalization method specified by XMLDSIG
           is used.

         - Concatenate the resulting octets to the final octet stream.
      */

      uint32_t i, n = document.getElement(vec, U_CONSTANT_TO_PARAM("ds:Reference"));

      for (i = 0; i < n; ++i)
         {
         x = vec[i];

         to_digest += UXML2Document::xmlC14N(x);
         }

      vec.clear();

      /*
      3) Take the following XMLDSIG elements in the order they are listed below, canonicalize each one and
         concatenate each resulting octet stream to the final octet stream:

         - The ds:SignedInfo element.
         - The ds:SignatureValue element.
         - The ds:KeyInfo element, if present.
      */

      if (document.getElement(vec, U_CONSTANT_TO_PARAM("ds:SignedInfo")))
         {
         x = vec[0];

         to_digest += UXML2Document::xmlC14N(x);
         }

      vec.clear();

      if (document.getElement(vec, U_CONSTANT_TO_PARAM("ds:SignatureValue")))
         {
         x = vec[0];

         to_digest += UXML2Document::xmlC14N(x);
         }

      vec.clear();

      if (document.getElement(vec, U_CONSTANT_TO_PARAM("ds:KeyInfo")))
         {
         x = vec[0];

         to_digest += UXML2Document::xmlC14N(x);
         }

      vec.clear();

      /*
      4) Take the unsigned signature properties that appear before the current xadesv141:ArchiveTimeStamp
         in the order they appear within the xades:UnsignedSignatureProperties, canonicalize each one and
         concatenate each resulting octet stream to the final octet stream. While concatenating the following
         rules apply:

         - The xades:CertificateValues property MUST be added if it is not already present and the
           ds:KeyInfo element does not contain the full set of certificates used to validate the electronic signature.

         - The xades:RevocationValues property MUST be added if it is not already present and the
           ds:KeyInfo element does not contain the revocation information that has to be shipped with the electronic signature.

         - The xades:AttrAuthoritiesCertValues property MUST be added if not already present and the following
           conditions are true: there exist an attribute certificate in the signature AND a number of certificates
           that have been used in its validation do not appear in CertificateValues. Its content will satisfy with
           the rules specified in clause 7.6.3.

         - The xades:AttributeRevocationValues property MUST be added if not already present and there the following
           conditions are true: there exist an attribute certificate AND some revocation data that have been used in
           its validation do not appear in RevocationValues. Its content will satisfy with the rules specified in clause 7.6.4.
      */

      if (document.getElement(vec, U_CONSTANT_TO_PARAM("xades:CompleteCertificateRefs")))
         {
         x = vec[0];

         to_digest += UXML2Document::xmlC14N(x);
         }

      vec.clear();

      if (document.getElement(vec, U_CONSTANT_TO_PARAM("xades:CertificateValues")))
         {
         x = vec[0];

         to_digest += UXML2Document::xmlC14N(x);
         }

      vec.clear();

      if (document.getElement(vec, U_CONSTANT_TO_PARAM("xades:CompleteRevocationRefs")))
         {
         x = vec[0];

         to_digest += UXML2Document::xmlC14N(x);
         }

      vec.clear();

      if (document.getElement(vec, U_CONSTANT_TO_PARAM("xades:RevocationValues")))
         {
         x = vec[0];

         to_digest += UXML2Document::xmlC14N(x);
         }

      vec.clear();

      if (document.getElement(vec, U_CONSTANT_TO_PARAM("xades:SignatureTimeStamp")))
         {
         x = vec[0];

         to_digest += UXML2Document::xmlC14N(x);
         }

      vec.clear();

      /*
      5) Take all the ds:Object elements except the one containing xades:QualifyingProperties element. Canonicalize each one
         and concatenate each resulting octet stream to the final octet stream. If ds:Canonicalization is present, the algorithm
         indicated by this element is used. If not, the standard canonicalization method specified by XMLDSIG is used.
      */

      n = document.getElement(vec, U_CONSTANT_TO_PARAM("ds:Object"));

      for (i = 0; i < n; ++i)
         {
         x = vec[i];

         if (x.find("xades:QualifyingProperties") == U_NOT_FOUND) to_digest += UXML2Document::xmlC14N(x);
         }

      u_base64_max_columns  = U_OPENSSL_BASE64_MAX_COLUMN;
      U_line_terminator_len = 2;

      UString archiveTimeStamp(U_CAPACITY), token = getTimeStampToken(to_digest, archive_timestamp);

      archiveTimeStamp.snprintf(U_XADES_ARCHIVE_TIMESTAMP_TEMPLATE, U_STRING_TO_TRACE(token));

      UString _output = UStringExt::substitute(content,
                             U_CONSTANT_TO_PARAM("        </xades:UnsignedSignatureProperties>"),
                             U_STRING_TO_PARAM(archiveTimeStamp));

      // ---------------------------------------------------------------------------------------------------------------
      // check for OOffice or MS-Word document...
      // ---------------------------------------------------------------------------------------------------------------
      utility.outputDocument(_output);
      // ---------------------------------------------------------------------------------------------------------------
      }
示例#5
0
   void run(int argc, char* argv[], char* env[])
      {
      U_TRACE(5, "Application::run(%d,%p,%p)", argc, argv, env)

      UApplication::run(argc, argv, env);

      U_SYSCALL_VOID_NO_PARAM(xmlInitParser); // init libxml

      LIBXML_TEST_VERSION

      // manage options

      num_args = (argc - optind);

      U_INTERNAL_DUMP("optind = %d num_args = %d", optind, num_args)

      if (UApplication::isOptions()) cfg_str = opt['c'];

      // manage file configuration

      if (cfg_str.empty()) cfg_str = U_STRING_FROM_CONSTANT("XAdES.ini");

      // ----------------------------------------------------------------------------------------------------------------------------------
      // XAdES - configuration parameters
      // ----------------------------------------------------------------------------------------------------------------------------------
      // DigestAlgorithm   md2 | md5 | sha | sha1 | sha224 | sha256 | sha384 | sha512 | mdc2 | ripmed160
      //
      // SigningTime this property contains the time at which the signer claims to have performed the signing process (yes/no)
      // ClaimedRole this property contains claimed or certified roles assumed by the signer in creating the signature
      //
      // this property contains the indication of the purported place where the signer claims to have produced the signature
      // -------------------------------------------------------------------------------------------------------------------
      // ProductionPlaceCity
      // ProductionPlaceStateOrProvince
      // ProductionPlacePostalCode
      // ProductionPlaceCountryName
      // -------------------------------------------------------------------------------------------------------------------
      //
      // DataObjectFormatMimeType   this property identifies the format of a signed data object (when electronic signatures
      //                            are not exchanged in a restricted context) to enable the presentation to the verifier or
      //                            use by the verifier (text, sound or video) in exactly the same way as intended by the signer
      //
      // CAStore
      // ArchiveTimeStamp           the time-stamp token within this property covers the archive validation data
      //
      // SignatureTimeStamp         the time-stamp token within this property covers the digital signature value element
      // Schema                     the pathname XML Schema of XAdES
      // ----------------------------------------------------------------------------------------------------------------------------------

      (void) cfg.open(cfg_str);

      UString x(U_CAPACITY);

      UServices::readEOF(STDIN_FILENO, x);

      if (x.empty()) U_ERROR("cannot read data from <stdin>...");

      (void) content.reserve(x.size());

      if (UBase64::decode(x, content) == false) U_ERROR("decoding data read failed...");

      // manage arguments...

      schema = ( U_SCHEMA == 0 ||
                *U_SCHEMA == '\0'
                  ? cfg[U_STRING_FROM_CONSTANT("XAdES-L.Schema")]
                  : UString(U_SCHEMA));

      if (schema.empty()) U_ERROR("error on XAdES schema: empty");

      /*
      UString str_CApath       = cfg[U_STRING_FROM_CONSTANT("XAdES-C.CAStore")],
              digest_algorithm = cfg[U_STRING_FROM_CONSTANT("XAdES-C.DigestAlgorithm")];

      if (str_CApath.empty() ||
          UServices::setupOpenSSLStore(0, str_CApath.c_str()) == false)
         {
         U_ERROR("error on setting CA Store: %S", str_CApath.data());
         }
      */

      UXML2Schema XAdES_schema(UFile::contentOf(schema));

      // ---------------------------------------------------------------------------------------------------------------
      // check for OOffice or MS-Word document...
      // ---------------------------------------------------------------------------------------------------------------
      utility.handlerConfig(cfg);

      if (utility.checkDocument(content, "XAdES", false)) content = utility.getSigned();
      // ---------------------------------------------------------------------------------------------------------------

      UApplication::exit_value = 1;

      UXML2Document document(content);

      if (XAdES_schema.validate(document) == false)
         {
         UString content1;

         if (document.getElement(content1, 0, U_CONSTANT_TO_PARAM(U_TAG_SIGNED_INFO)) &&
             content1.empty() == false)
            {
            UXML2Document document1(content1);

            if (XAdES_schema.validate(document1) == false)
               {
               U_ERROR("fail to validate data input based on XAdES schema");
               }
            }
         }

      UDSIGContext dsigCtx;
      UString data, signature;
      const char* digest_algorithm;

      if (dsigCtx.verify(document, digest_algorithm, data, signature))
         {
         UString element = document.getElementData(128, U_CONSTANT_TO_PARAM(U_TAG_X509_CERTIFICATE));

         if (element.empty() == false)
            {
            UString certificate(element.size());

            if (UBase64::decode(element, certificate))
               {
               alg = u_dgst_get_algoritm(digest_algorithm);

               if (alg == -1) U_ERROR("I can't find the digest algorithm for: %s", digest_algorithm);

               X509* x509 = UCertificate::readX509(certificate, "DER");

               u_pkey = UCertificate::getSubjectPublicKey(x509);

               U_SYSCALL_VOID(X509_free, "%p", x509);

               if (UServices::verifySignature(alg, data, signature, UString::getStringNull(), 0))
                  {
                  UApplication::exit_value = 0;

#              ifdef __MINGW32__
                  (void) setmode(1, O_BINARY);
#              endif

               // std::cout.write(U_STRING_TO_PARAM(certificate));
                  std::cout.write(U_STRING_TO_PARAM(content));
                  }

               U_SYSCALL_VOID(EVP_PKEY_free, "%p", u_pkey);
                                                   u_pkey = 0;
               }
            }
         }

      utility.clean();
      }
示例#6
0
文件: sign.cpp 项目: rowanthorpe/ULib
   void run(int argc, char* argv[], char* env[])
      {
      U_TRACE(5, "Application::run(%d,%p,%p)", argc, argv, env)

      UApplication::run(argc, argv, env);

      U_SYSCALL_VOID_NO_PARAM(xmlInitParser); // init libxml

      LIBXML_TEST_VERSION

      // manage options

      num_args = (argc - optind);

      U_INTERNAL_DUMP("optind = %d num_args = %d", optind, num_args)

      if (UApplication::isOptions()) cfg_str = opt['c'];

      // manage file configuration

      if (cfg_str.empty()) cfg_str = U_STRING_FROM_CONSTANT("XAdES.ini");

      // ----------------------------------------------------------------------------------------------------------------------------------
      // XAdES signature - configuration parameters
      // ----------------------------------------------------------------------------------------------------------------------------------
      // DigestAlgorithm   md2 | md5 | sha | sha1 | sha224 | sha256 | sha384 | sha512 | mdc2 | ripmed160
      //
      // SigningTime this property contains the time at which the signer claims to have performed the signing process (yes/no)
      // ClaimedRole this property contains claimed or certified roles assumed by the signer in creating the signature
      //
      // this property contains the indication of the purported place where the signer claims to have produced the signature
      // -------------------------------------------------------------------------------------------------------------------
      // ProductionPlaceCity
      // ProductionPlaceStateOrProvince
      // ProductionPlacePostalCode
      // ProductionPlaceCountryName
      // -------------------------------------------------------------------------------------------------------------------
      //
      // DataObjectFormatMimeType   this property identifies the format of a signed data object (when electronic signatures
      //                            are not exchanged in a restricted context) to enable the presentation to the verifier or
      //                            use by the verifier (text, sound or video) in exactly the same way as intended by the signer
      //
      // CAStore
      // ArchiveTimeStamp           the time-stamp token within this property covers the archive validation data
      //
      // SignatureTimeStamp         the time-stamp token within this property covers the digital signature value element
      // Schema                     the pathname XML Schema of XAdES
      // ----------------------------------------------------------------------------------------------------------------------------------

      cfg.UFile::setPath(cfg_str);

      UString x(U_CAPACITY);

      UServices::readEOF(STDIN_FILENO, x);

      if (x.empty()) U_ERROR("cannot read data from <stdin>");

      (void) document.reserve(x.size());

      UBase64::decode(x, document);

      if (document.empty()) U_ERROR("decoding data read failed");

      // manage arguments...

      if ( U_DATA_URI &&
          *U_DATA_URI == '\0')
         {
         U_ERROR("DATA_URI is mandatory");
         }

      if ( U_X509 &&
          *U_X509 == '\0')
         {
         U_ERROR("X509 is mandatory");
         }

      if ( U_KEY_HANDLE &&
          *U_KEY_HANDLE == '\0')
         {
         U_ERROR("KEY_HANDLE is mandatory");
         }

      UCertificate cert(UString(U_X509));

      if (cert.isValid() == false) U_ERROR("certificate not valid");

      U_INTERNAL_DUMP("U_CA_STORE = %S", U_CA_STORE)

      xades_c = (U_CA_STORE != U_NULLPTR);

      digest_algorithm = getOptionValue(U_DIGEST_ALGORITHM, "DigestAlgorithm");

      alg = u_dgst_get_algoritm(digest_algorithm.c_str());

      if (alg == -1) U_ERROR("I can't find the digest algorithm for: %s", digest_algorithm.data());

      signing_time                       = getOptionValue(U_SIGNING_TIME,                       "SigningTime").strtol();
      claimed_role                       = getOptionValue(U_CLAIMED_ROLE,                       "ClaimedRole");
      production_place_city              = getOptionValue(U_PRODUCTION_PLACE_CITY,              "ProductionPlaceCity");
      production_place_state_or_province = getOptionValue(U_PRODUCTION_PLACE_STATE_OR_PROVINCE, "ProductionPlaceStateOrProvince");
      production_place_postal_code       = getOptionValue(U_PRODUCTION_PLACE_POSTAL_CODE,       "ProductionPlacePostalCode");
      production_place_country_name      = getOptionValue(U_PRODUCTION_PLACE_COUNTRY_NAME,      "ProductionPlaceCountryName");
      data_object_format_mimetype        = getOptionValue("",                                   "DataObjectFormatMimeType");

      if (xades_c == false) num_ca = 0;
      else
         {
         // XAdES-C
         // -------------------------------------------------------------------------------------------------------------  
         str_CApath          = getOptionValue(U_CA_STORE,            "CAStore");
         signature_timestamp = getOptionValue(U_SIGNATURE_TIMESTAMP, "SignatureTimeStamp");

         if (str_CApath.empty() ||
             UServices::setupOpenSSLStore(U_NULLPTR, str_CApath.c_str()) == false)
            {
            U_ERROR("error on setting CA Store: %S", str_CApath.data());
            }

         num_ca = cert.getSignerCertificates(vec_ca, U_NULLPTR, 0);

         if (UCertificate::verify_result == false)
            {
            UServices::setVerifyStatus();

            U_ERROR("error on verifying the certificate: %.*s", u_buffer_len, u_buffer);
            }
         // -------------------------------------------------------------------------------------------------------------  
         }

      u_base64_max_columns  = U_OPENSSL_BASE64_MAX_COLUMN;
      U_line_terminator_len = 2;

      UString modulus          = cert.getModulus(),
              exponent         = cert.getExponent();
              X509IssuerName   = cert.getIssuerForLDAP(),
              X509SubjectName  = cert.getSubjectForLDAP(),
              X509Certificate  = cert.getEncoded("DER");
              X509SerialNumber = cert.getSerialNumber();

      UString X509CertificateValue(U_CAPACITY), KeyInfo(U_CAPACITY);

      UBase64::encode(X509Certificate, X509CertificateValue);

      u_base64_max_columns = 0;

      KeyInfo.snprintf(U_CONSTANT_TO_PARAM(U_XMLDSIG_KEYINFO_TEMPLATE),
                       U_STRING_TO_TRACE(modulus),
                       U_STRING_TO_TRACE(exponent),
                       U_STRING_TO_TRACE(X509SubjectName),
                       U_STRING_TO_TRACE(X509IssuerName),
                       X509SerialNumber,
                       U_STRING_TO_TRACE(X509CertificateValue));

      UString ObjectDigestValue(200U),
              Reference(U_CAPACITY), dataObjectFormat(U_CAPACITY),
              XMLDSIGReference(U_CAPACITY), XMLDSIGReferenceC14N(U_CAPACITY);

      // ---------------------------------------------------------------------------------------------------------------
      // check for OOffice or MS-Word document...
      // ---------------------------------------------------------------------------------------------------------------
      utility.handlerConfig(cfg);

      (void) utility.checkDocument(document, U_DATA_URI, true);
      // ---------------------------------------------------------------------------------------------------------------

      for (uint32_t i = 0, n = utility.vdocument.size(); i < n; ++i)
         {
         uri       = utility.vuri[i];
         to_digest = utility.vdocument[i];

         // ---------------------------------------------------------------------------------------------------------------
         // 2. Compute the message digest of the text, m = Hash(C).
         // ---------------------------------------------------------------------------------------------------------------
         ObjectDigestValue.setEmpty();

         UServices::generateDigest(alg, 0, to_digest, ObjectDigestValue, true);
         // ---------------------------------------------------------------------------------------------------------------

         Reference.snprintf(U_CONSTANT_TO_PARAM(U_XMLDSIG_REFERENCE_TEMPLATE), uri.c_str(),
                            U_STRING_TO_TRACE(digest_algorithm),
                            U_STRING_TO_TRACE(ObjectDigestValue));

         XMLDSIGReference     +=                        Reference;
         XMLDSIGReferenceC14N += UXML2Document::xmlC14N(Reference);

         if (data_object_format_mimetype.empty() == false)
            {
            dataObjectFormat.snprintf(U_CONSTANT_TO_PARAM(U_XADES_DATA_OBJECT_FORMAT_TEMPLATE), uri.c_str(), U_STRING_TO_TRACE(data_object_format_mimetype));

            DataObjectFormat += dataObjectFormat;
            }
         }

      setXAdESReference(); // XAdES management

      // ---------------------------------------------------------------------------------------------------------------
      // 3. Encapsulate the message digest in an XML <SignedInfo> element, SI, in canonicalized form.
      // ---------------------------------------------------------------------------------------------------------------
      UString SignedInfo(U_CONSTANT_SIZE(U_XMLDSIG_SIGNED_INFO_TEMPLATE) + XMLDSIGReference.size() + XAdESReference.size());

      SignedInfo.snprintf(U_CONSTANT_TO_PARAM(U_XMLDSIG_SIGNED_INFO_TEMPLATE),
                          U_STRING_TO_TRACE(digest_algorithm),
                          U_STRING_TO_TRACE(XMLDSIGReference),
                          U_STRING_TO_TRACE(XAdESReference));

      UString to_sign = UXML2Document::xmlC14N(SignedInfo);
      // ---------------------------------------------------------------------------------------------------------------

      // ---------------------------------------------------------------------------------------------------------------
      // 4. Compute the RSA signatureValue of the canonicalized <SignedInfo> element, SV = RsaSign(Ks, SI).
      // ---------------------------------------------------------------------------------------------------------------
      UString SignatureValue(U_CAPACITY), signatureTimeStamp(U_CAPACITY), archiveTimeStamp(U_CAPACITY);

      u_base64_max_columns = U_OPENSSL_BASE64_MAX_COLUMN;

      ENGINE* e;

#  ifdef _MSWINDOWS_
      e = UServices::loadEngine("HCSP", ENGINE_METHOD_RSA);
      x = U_KEY_HANDLE;
#  else
      e = U_NULLPTR;
      x = UFile::contentOf(UString(U_KEY_HANDLE));

      if (x.empty() ||
          (u_pkey = UServices::loadKey(x, U_NULLPTR, true, U_NULLPTR, e)) == U_NULLPTR)
         {
         U_ERROR("I can't load the private key: %S", U_KEY_HANDLE);
         }

#     ifdef HAVE_OPENSSL_98
      if (cert.matchPrivateKey(u_pkey) == false) U_ERROR("the private key doesn't matches the public key of the certificate");
#     endif

      x.clear();
#  endif

      UString sign = UServices::getSignatureValue(alg, to_sign, x, UString::getStringNull(), true, e);

      u_base64_max_columns = 0;

      SignatureValue.snprintf(U_CONSTANT_TO_PARAM(U_XMLDSIG_SIGNATURE_VALUE_TEMPLATE), U_STRING_TO_TRACE(sign));

      if (signature_timestamp.empty() == false)
         {
         to_digest = UXML2Document::xmlC14N(SignatureValue);

         UString token = getTimeStampToken(to_digest, signature_timestamp);

         signatureTimeStamp.snprintf(U_CONSTANT_TO_PARAM(U_XADES_SIGNATURE_TIMESTAMP_TEMPLATE), U_STRING_TO_TRACE(token));
         }

      // XAdES-C
      // -------------------------------------------------------------------------------------------------------------  
      if (xades_c) setXAdESUnsignedSignatureProperties();
      // -------------------------------------------------------------------------------------------------------------  

      (void) XAdESObject.reserve(U_CONSTANT_SIZE(U_XADES_TEMPLATE) +
                          signedProperties.size() +
                          unsignedSignatureProperties.size() +
                          archiveTimeStamp.size() +
                          signatureTimeStamp.size());

      XAdESObject.snprintf(U_CONSTANT_TO_PARAM(U_XADES_TEMPLATE),
                           U_STRING_TO_TRACE(signedProperties),
                           U_STRING_TO_TRACE(unsignedSignatureProperties),
                           U_STRING_TO_TRACE(archiveTimeStamp),
                           U_STRING_TO_TRACE(signatureTimeStamp));
      // ---------------------------------------------------------------------------------------------------------------

      // ---------------------------------------------------------------------------------------------------------------
      // 5. Compose the final XML document including the signatureValue, this time in non-canonicalized form.
      // ---------------------------------------------------------------------------------------------------------------
      UString output(U_CONSTANT_SIZE(U_XMLDSIG_TEMPLATE) + 8192U + 
                     SignedInfo.size() + SignatureValue.size() + XAdESObject.size());

      if (utility.ooffice)
         {
         OpenDocumentStart = U_STRING_FROM_CONSTANT("<document-signatures xmlns=\"urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0\">");
         OpenDocumentEnd   = U_STRING_FROM_CONSTANT("</document-signatures>");
         }

      output.snprintf(U_CONSTANT_TO_PARAM(U_XMLDSIG_TEMPLATE),
                        U_STRING_TO_TRACE(OpenDocumentStart),
                        U_STRING_TO_TRACE(SignedInfo),
                        U_STRING_TO_TRACE(SignatureValue),
                        U_STRING_TO_TRACE(KeyInfo),
                        U_STRING_TO_TRACE(XAdESObject),
                        U_STRING_TO_TRACE(OpenDocumentEnd));
      // ---------------------------------------------------------------------------------------------------------------

      // ---------------------------------------------------------------------------------------------------------------
      // check for OOffice or MS-Word document...
      // ---------------------------------------------------------------------------------------------------------------
      utility.outputDocument(output);
      // ---------------------------------------------------------------------------------------------------------------
      }