[Libreoffice-commits] core.git: include/vcl vcl/source

Ashod Nakashian ashod.nakashian at collabora.co.uk
Sun Jul 16 03:17:02 UTC 2017


 include/vcl/filter/pdfdocument.hxx     |    2 
 vcl/source/filter/ipdf/pdfdocument.cxx |   13 
 vcl/source/gdi/pdfwriter_impl.cxx      | 1846 ---------------------------------
 3 files changed, 18 insertions(+), 1843 deletions(-)

New commits:
commit d38627b26ee80ae7e330fdedea1058d35a48b92b
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Fri Jul 14 22:21:25 2017 -0400

    vcl: use svl signing and remove moved code
    
    Change-Id: Id875a675d7ab649c9223ecca5de2da69ff4b8786
    Reviewed-on: https://gerrit.libreoffice.org/39718
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/include/vcl/filter/pdfdocument.hxx b/include/vcl/filter/pdfdocument.hxx
index 362d5e637e9e..09288326e921 100644
--- a/include/vcl/filter/pdfdocument.hxx
+++ b/include/vcl/filter/pdfdocument.hxx
@@ -227,7 +227,7 @@ enum class XRefEntryType
     FREE,
     /// xref "n" or xref stream "1".
     NOT_COMPRESSED,
-    /// xref stream "2.
+    /// xref stream "2".
     COMPRESSED
 };
 
diff --git a/vcl/source/filter/ipdf/pdfdocument.cxx b/vcl/source/filter/ipdf/pdfdocument.cxx
index 1dd186e92801..6ec4ba98c1ca 100644
--- a/vcl/source/filter/ipdf/pdfdocument.cxx
+++ b/vcl/source/filter/ipdf/pdfdocument.cxx
@@ -25,6 +25,7 @@
 #include <sal/log.hxx>
 #include <sal/types.h>
 #include <sax/tools/converter.hxx>
+#include <svl/cryptosign.hxx>
 #include <tools/zcodec.hxx>
 #include <unotools/calendarwrapper.hxx>
 #include <unotools/datetime.hxx>
@@ -837,14 +838,10 @@ bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificat
     m_aEditBuffer.ReadBytes(aBuffer2.get(), nBufferSize2);
 
     OStringBuffer aCMSHexBuffer;
-    vcl::PDFWriter::PDFSignContext aSignContext(aCMSHexBuffer);
-    aSignContext.m_pDerEncoded = aDerEncoded.getArray();
-    aSignContext.m_nDerEncoded = aDerEncoded.getLength();
-    aSignContext.m_pByteRange1 = aBuffer1.get();
-    aSignContext.m_nByteRange1 = nBufferSize1;
-    aSignContext.m_pByteRange2 = aBuffer2.get();
-    aSignContext.m_nByteRange2 = nBufferSize2;
-    if (!vcl::PDFWriter::Sign(aSignContext))
+    svl::crypto::Signing aSigning(xCertificate);
+    aSigning.AddDataRange(aBuffer1.get(), nBufferSize1);
+    aSigning.AddDataRange(aBuffer2.get(), nBufferSize2);
+    if (!aSigning.Sign(aCMSHexBuffer))
     {
         SAL_WARN("vcl.filter", "PDFDocument::Sign: PDFWriter::Sign() failed");
         return false;
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index ac9dec1c54b7..5fa7b9a40350 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -61,6 +61,7 @@
 #include <tools/stream.hxx>
 #include <tools/urlobj.hxx>
 #include <tools/zcodec.hxx>
+#include <svl/cryptosign.hxx>
 #include <vcl/bitmapex.hxx>
 #include <vcl/bitmapaccess.hxx>
 #include <vcl/cvtgrf.hxx>
@@ -5382,1765 +5383,8 @@ bool PDFWriterImpl::emitSignature()
     return true;
 }
 
-#if HAVE_FEATURE_NSS && !defined(_WIN32)
-
-namespace {
-
-char *PDFSigningPKCS7PasswordCallback(PK11SlotInfo * /*slot*/, PRBool /*retry*/, void *arg)
-{
-    return PL_strdup(static_cast<char *>(arg));
-}
-
-// ASN.1 used in the (much simpler) time stamp request. From RFC3161
-// and other sources.
-
-/*
-AlgorithmIdentifier  ::=  SEQUENCE  {
-     algorithm  OBJECT IDENTIFIER,
-     parameters ANY DEFINED BY algorithm OPTIONAL  }
-                   -- contains a value of the type
-                   -- registered for use with the
-                   -- algorithm object identifier value
-
-MessageImprint ::= SEQUENCE  {
-    hashAlgorithm AlgorithmIdentifier,
-    hashedMessage OCTET STRING  }
-*/
-
-typedef struct {
-    SECAlgorithmID hashAlgorithm;
-    SECItem hashedMessage;
-} MessageImprint;
-
-/*
-Extension  ::=  SEQUENCE  {
-    extnID    OBJECT IDENTIFIER,
-    critical  BOOLEAN DEFAULT FALSE,
-    extnValue OCTET STRING  }
-*/
-
-typedef struct {
-    SECItem extnID;
-    SECItem critical;
-    SECItem extnValue;
-} Extension;
-
-/*
-Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
-*/
-
-/*
-TSAPolicyId ::= OBJECT IDENTIFIER
-
-TimeStampReq ::= SEQUENCE  {
-    version            INTEGER  { v1(1) },
-    messageImprint     MessageImprint,
-    --a hash algorithm OID and the hash value of the data to be
-    --time-stamped
-    reqPolicy          TSAPolicyId         OPTIONAL,
-    nonce              INTEGER             OPTIONAL,
-    certReq            BOOLEAN             DEFAULT FALSE,
-    extensions     [0] IMPLICIT Extensions OPTIONAL  }
-*/
-
-typedef struct {
-    SECItem version;
-    MessageImprint messageImprint;
-    SECItem reqPolicy;
-    SECItem nonce;
-    SECItem certReq;
-    Extension *extensions;
-} TimeStampReq;
-
-/**
- * General name, defined by RFC 3280.
- */
-struct GeneralName
-{
-    CERTName name;
-};
-
-/**
- * List of general names (only one for now), defined by RFC 3280.
- */
-struct GeneralNames
-{
-    GeneralName names;
-};
-
-/**
- * Supplies different fields to identify a certificate, defined by RFC 5035.
- */
-struct IssuerSerial
-{
-    GeneralNames issuer;
-    SECItem serialNumber;
-};
-
-/**
- * Supplies different fields that are used to identify certificates, defined by
- * RFC 5035.
- */
-struct ESSCertIDv2
-{
-    SECAlgorithmID hashAlgorithm;
-    SECItem certHash;
-    IssuerSerial issuerSerial;
-};
-
-/**
- * This attribute uses the ESSCertIDv2 structure, defined by RFC 5035.
- */
-struct SigningCertificateV2
-{
-    ESSCertIDv2** certs;
-
-    SigningCertificateV2()
-        : certs(nullptr)
-    {
-    }
-};
-
-// (Partial) ASN.1 for the time stamp response. Very complicated. Pulled
-// together from various RFCs.
-
-/*
-Accuracy ::= SEQUENCE {
-    seconds     INTEGER          OPTIONAL,
-    millis  [0] INTEGER (1..999) OPTIONAL,
-    micros  [1] INTEGER (1..999) OPTIONAL  }
-
-PKIStatus ::= INTEGER {
-    granted                (0),
-    -- when the PKIStatus contains the value zero a TimeStampToken, as requested, is present.
-    grantedWithMods        (1),
-     -- when the PKIStatus contains the value one a TimeStampToken, with modifications, is present.
-    rejection              (2),
-    waiting                (3),
-    revocationWarning      (4),
-     -- this message contains a warning that a revocation is
-     -- imminent
-    revocationNotification (5)
-     -- notification that a revocation has occurred
-}
-
-PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
-    -- text encoded as UTF-8 String [RFC3629] (note: each
-    -- UTF8String MAY include an [RFC3066] language tag
-    -- to indicate the language of the contained text
-    -- see [RFC2482] for details)
-
-PKIFailureInfo ::= BIT STRING {
-    badAlg               (0),
-      -- unrecognized or unsupported Algorithm Identifier
-    badRequest           (2),
-      -- transaction not permitted or supported
-    badDataFormat        (5),
-      -- the data submitted has the wrong format
-    timeNotAvailable    (14),
-      -- the TSA's time source is not available
-    unacceptedPolicy    (15),
-      -- the requested TSA policy is not supported by the TSA.
-    unacceptedExtension (16),
-      -- the requested extension is not supported by the TSA.
-    addInfoNotAvailable (17),
-      -- the additional information requested could not be understood
-      -- or is not available
-    systemFailure       (25)
-      -- the request cannot be handled due to system failure
-}
-
-PKIStatusInfo ::= SEQUENCE {
-    status       PKIStatus,
-    statusString PKIFreeText    OPTIONAL,
-    failInfo     PKIFailureInfo OPTIONAL  }
-
-ContentType ::= OBJECT IDENTIFIER
-
-ContentInfo ::= SEQUENCE {
-    contentType     ContentType,
-    content     [0] EXPLICIT ANY DEFINED BY contentType }
-
-CMSVersion ::= INTEGER { v0(0), v1(1), v2(2), v3(3), v4(4), v5(5) }
-
-DigestAlgorithmIdentifier ::= AlgorithmIdentifier
-
-DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
-
-ContentType ::= OBJECT IDENTIFIER
-
-EncapsulatedContentInfo ::= SEQUENCE {
-    eContentType     ContentType,
-    eContent     [0] EXPLICIT OCTET STRING OPTIONAL }
-
-OtherCertificateFormat ::= SEQUENCE {
-    otherCertFormat OBJECT IDENTIFIER,
-    otherCert       ANY DEFINED BY otherCertFormat }
-
-CertificateChoices ::= CHOICE {
-    certificate             Certificate,
-    extendedCertificate [0] IMPLICIT ExtendedCertificate, -- Obsolete
-    v1AttrCert          [1] IMPLICIT AttributeCertificateV1,       -- Obsolete
-    v2AttrCert          [2] IMPLICIT AttributeCertificateV2,
-    other               [3] IMPLICIT OtherCertificateFormat }
-
-CertificateSet ::= SET OF CertificateChoices
-
-CertificateList  ::=  SEQUENCE  {
-    tbsCertList        TBSCertList,
-    signatureAlgorithm AlgorithmIdentifier,
-    signatureValue     BIT STRING  }
-
-TBSCertList  ::=  SEQUENCE  {
-    version                 Version OPTIONAL,
-                                  -- if present, MUST be v2
-    signature               AlgorithmIdentifier,
-    issuer                  Name,
-    thisUpdate              Time,
-    nextUpdate              Time OPTIONAL,
-    revokedCertificates     SEQUENCE OF SEQUENCE  {
-        userCertificate         CertificateSerialNumber,
-        revocationDate          Time,
-        crlEntryExtensions      Extensions OPTIONAL
-                                   -- if present, version MUST be v2
-                            }  OPTIONAL,
-    crlExtensions       [0] EXPLICIT Extensions OPTIONAL
-                                   -- if present, version MUST be v2
-                            }
-
-OtherRevocationInfoFormat ::= SEQUENCE {
-  otherRevInfoFormat OBJECT IDENTIFIER,
-  otherRevInfo ANY DEFINED BY otherRevInfoFormat }
-
-RevocationInfoChoice ::= CHOICE {
-    crl       CertificateList,
-    other [1] IMPLICIT OtherRevocationInfoFormat }
-
-RevocationInfoChoices ::= SET OF RevocationInfoChoice
-
-SignerIdentifier ::= CHOICE {
-    issuerAndSerialNumber IssuerAndSerialNumber,
-    subjectKeyIdentifier [0] SubjectKeyIdentifier }
-
-AttributeValue ::= ANY
-
-Attribute ::= SEQUENCE {
-    attrType OBJECT IDENTIFIER,
-    attrValues SET OF AttributeValue }
-
-SignedAttributes ::= SET SIZE (1..MAX) OF Attribute
-
-SignatureValue ::= OCTET STRING
-
-UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute
-
-SignerInfo ::= SEQUENCE {
-    version CMSVersion,
-    sid SignerIdentifier,
-    digestAlgorithm DigestAlgorithmIdentifier,
-    signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
-    signatureAlgorithm SignatureAlgorithmIdentifier,
-    signature SignatureValue,
-    unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }
-
-SignerInfos ::= SET OF SignerInfo
-
-SignedData ::= SEQUENCE {
-    version                       CMSVersion,
-    digestAlgorithms              DigestAlgorithmIdentifiers,
-    encapContentInfo              EncapsulatedContentInfo,
-    certificates     [0] IMPLICIT CertificateSet              OPTIONAL,
-    crls             [1] IMPLICIT RevocationInfoChoices       OPTIONAL,
-    signerInfos                   SignerInfos }
-
-TimeStampToken ::= ContentInfo
-    -- contentType is id-signedData as defined in [CMS]
-    -- content is SignedData as defined in([CMS])
-    -- eContentType within SignedData is id-ct-TSTInfo
-    -- eContent within SignedData is TSTInfo
-
-TSTInfo ::= SEQUENCE  {
-    version            INTEGER  { v1(1) },
-    policy             TSAPolicyId,
-    messageImprint     MessageImprint,
-      -- MUST have the same value as the similar field in
-      -- TimeStampReq
-    serialNumber       INTEGER,
-     -- Time-Stamping users MUST be ready to accommodate integers
-     -- up to 160 bits.
-    genTime            GeneralizedTime,
-    accuracy           Accuracy            OPTIONAL,
-    ordering           BOOLEAN             DEFAULT FALSE,
-    nonce              INTEGER             OPTIONAL,
-      -- MUST be present if the similar field was present
-      -- in TimeStampReq.  In that case it MUST have the same value.
-    tsa            [0] GeneralName         OPTIONAL,
-    extensions     [1] IMPLICIT Extensions OPTIONAL   }
-
-TimeStampResp ::= SEQUENCE  {
-     status         PKIStatusInfo,
-     timeStampToken TimeStampToken OPTIONAL  }
-*/
-
-const SEC_ASN1Template MessageImprint_Template[] =
-{
-    { SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(MessageImprint) },
-    { SEC_ASN1_INLINE, offsetof(MessageImprint, hashAlgorithm), SECOID_AlgorithmIDTemplate, 0 },
-    { SEC_ASN1_OCTET_STRING, offsetof(MessageImprint, hashedMessage), nullptr, 0 },
-    { 0, 0, nullptr, 0 }
-};
-
-const SEC_ASN1Template Extension_Template[] =
-{
-    { SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(Extension) },
-    { SEC_ASN1_OBJECT_ID, offsetof(Extension, extnID), nullptr, 0 },
-    { SEC_ASN1_BOOLEAN, offsetof(Extension, critical), nullptr, 0 },
-    { SEC_ASN1_OCTET_STRING, offsetof(Extension, extnValue), nullptr, 0 },
-    { 0, 0, nullptr, 0 }
-};
-
-const SEC_ASN1Template Extensions_Template[] =
-{
-    { SEC_ASN1_SEQUENCE_OF, 0, Extension_Template, 0 }
-};
-
-const SEC_ASN1Template TimeStampReq_Template[] =
-{
-    { SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(TimeStampReq) },
-    { SEC_ASN1_INTEGER, offsetof(TimeStampReq, version), nullptr, 0 },
-    { SEC_ASN1_INLINE, offsetof(TimeStampReq, messageImprint), MessageImprint_Template, 0 },
-    { SEC_ASN1_OBJECT_ID | SEC_ASN1_OPTIONAL, offsetof(TimeStampReq, reqPolicy), nullptr, 0 },
-    { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof(TimeStampReq, nonce), nullptr, 0 },
-    { SEC_ASN1_BOOLEAN | SEC_ASN1_OPTIONAL, offsetof(TimeStampReq, certReq), nullptr, 0 },
-    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 0, offsetof(TimeStampReq, extensions), Extensions_Template, 0 },
-    { 0, 0, nullptr, 0 }
-};
-
-/**
- * GeneralName ::= CHOICE {
- *      otherName                       [0]     OtherName,
- *      rfc822Name                      [1]     IA5String,
- *      dNSName                         [2]     IA5String,
- *      x400Address                     [3]     ORAddress,
- *      directoryName                   [4]     Name,
- *      ediPartyName                    [5]     EDIPartyName,
- *      uniformResourceIdentifier       [6]     IA5String,
- *      iPAddress                       [7]     OCTET STRING,
- *      registeredID                    [8]     OBJECT IDENTIFIER
- * }
- */
-const SEC_ASN1Template GeneralNameTemplate[] =
-{
-    {SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(GeneralName)},
-    {SEC_ASN1_INLINE, offsetof(GeneralName, name), CERT_NameTemplate, 0},
-    {0, 0, nullptr, 0}
-};
-
-/**
- * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
- */
-const SEC_ASN1Template GeneralNamesTemplate[] =
-{
-    {SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(GeneralNames)},
-    {SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 4, offsetof(GeneralNames, names), GeneralNameTemplate, 0},
-    {0, 0, nullptr, 0}
-};
-
-/**
- * IssuerSerial ::= SEQUENCE {
- *     issuer GeneralNames,
- *     serialNumber CertificateSerialNumber
- * }
- */
-const SEC_ASN1Template IssuerSerialTemplate[] =
-{
-    {SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(IssuerSerial)},
-    {SEC_ASN1_INLINE, offsetof(IssuerSerial, issuer), GeneralNamesTemplate, 0},
-    {SEC_ASN1_INTEGER, offsetof(IssuerSerial, serialNumber), nullptr, 0},
-    {0, 0, nullptr, 0}
-};
-
-/**
- * Hash ::= OCTET STRING
- *
- * ESSCertIDv2 ::= SEQUENCE {
- *     hashAlgorithm AlgorithmIdentifier DEFAULT {algorithm id-sha256},
- *     certHash Hash,
- *     issuerSerial IssuerSerial OPTIONAL
- * }
- */
-const SEC_ASN1Template ESSCertIDv2Template[] =
-{
-    {SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(ESSCertIDv2)},
-    {SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(ESSCertIDv2, hashAlgorithm), SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate), 0},
-    {SEC_ASN1_OCTET_STRING, offsetof(ESSCertIDv2, certHash), nullptr, 0},
-    {SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(ESSCertIDv2, issuerSerial), IssuerSerialTemplate, 0},
-    {0, 0, nullptr, 0}
-};
-
-/**
- * SigningCertificateV2 ::= SEQUENCE {
- * }
- */
-const SEC_ASN1Template SigningCertificateV2Template[] =
-{
-    {SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(SigningCertificateV2)},
-    {SEC_ASN1_SEQUENCE_OF, offsetof(SigningCertificateV2, certs), ESSCertIDv2Template, 0},
-    {0, 0, nullptr, 0}
-};
-
-typedef struct {
-    SECItem status;
-    SECItem statusString;
-    SECItem failInfo;
-} PKIStatusInfo;
-
-const SEC_ASN1Template PKIStatusInfo_Template[] =
-{
-    { SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(PKIStatusInfo) },
-    { SEC_ASN1_INTEGER, offsetof(PKIStatusInfo, status), nullptr, 0 },
-    { SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE | SEC_ASN1_OPTIONAL, offsetof(PKIStatusInfo, statusString), nullptr, 0 },
-    { SEC_ASN1_BIT_STRING | SEC_ASN1_OPTIONAL, offsetof(PKIStatusInfo, failInfo), nullptr, 0 },
-    { 0, 0, nullptr, 0 }
-};
-
-const SEC_ASN1Template Any_Template[] =
-{
-    { SEC_ASN1_ANY, 0, nullptr, sizeof(SECItem) }
-};
-
-typedef struct {
-    PKIStatusInfo status;
-    SECItem timeStampToken;
-} TimeStampResp;
-
-const SEC_ASN1Template TimeStampResp_Template[] =
-{
-    { SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(TimeStampResp) },
-    { SEC_ASN1_INLINE, offsetof(TimeStampResp, status), PKIStatusInfo_Template, 0 },
-    { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL, offsetof(TimeStampResp, timeStampToken), Any_Template, 0 },
-    { 0, 0, nullptr, 0 }
-};
-
-/* Will see if these are needed or not
-typedef struct {
-    SECItem seconds;
-    SECItem millis;
-    SECItem micros;
-} Accuracy;
-
-const SEC_ASN1Template Integer_Template[] =
-{
-    { SEC_ASN1_INTEGER, 0, NULL, sizeof(SECItem) }
-};
-
-const SEC_ASN1Template Accuracy_Template[] =
-{
-    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(Accuracy) },
-    { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof(Accuracy, seconds), 0, 0 },
-    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 0, offsetof(Accuracy, millis), Integer_Template, 0 },
-    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 1, offsetof(Accuracy, micros), Integer_Template, 0 },
-    { 0, 0, 0, 0 }
-};
-*/
-
-size_t AppendToBuffer(char *ptr, size_t size, size_t nmemb, void *userdata)
-{
-    OStringBuffer *pBuffer = static_cast<OStringBuffer*>(userdata);
-    pBuffer->append(ptr, size*nmemb);
-
-    return size*nmemb;
-}
-
-OUString PKIStatusToString(int n)
-{
-    switch (n)
-    {
-    case 0: return OUString("granted");
-    case 1: return OUString("grantedWithMods");
-    case 2: return OUString("rejection");
-    case 3: return OUString("waiting");
-    case 4: return OUString("revocationWarning");
-    case 5: return OUString("revocationNotification");
-    default: return "unknown (" + OUString::number(n) + ")";
-    }
-}
-
-OUString PKIStatusInfoToString(const PKIStatusInfo& rStatusInfo)
-{
-    OUString result;
-
-    result += "{status=";
-    if (rStatusInfo.status.len == 1)
-        result += PKIStatusToString(rStatusInfo.status.data[0]);
-    else
-        result += "unknown (len=" + OUString::number(rStatusInfo.status.len);
-
-    // FIXME: Perhaps look at rStatusInfo.statusString.data but note
-    // that we of course can't assume it contains proper UTF-8. After
-    // all, it is data from an external source. Also, RFC3161 claims
-    // it should be a SEQUENCE (1..MAX) OF UTF8String, but another
-    // source claimed it would be a single UTF8String, hmm?
-
-    // FIXME: Worth it to decode failInfo to cleartext, probably not at least as long as this is only for a SAL_INFO
-
-    result += "}";
-
-    return result;
-}
-
-// SEC_StringToOID() and NSS_CMSSignerInfo_AddUnauthAttr() are
-// not exported from libsmime, so copy them here. Sigh.
-
-SECStatus
-my_SEC_StringToOID(SECItem *to, const char *from, PRUint32 len)
-{
-    PRUint32 decimal_numbers = 0;
-    PRUint32 result_bytes = 0;
-    SECStatus rv;
-    PRUint8 result[1024];
-
-    static const PRUint32 max_decimal = (0xffffffff / 10);
-    static const char OIDstring[] = {"OID."};
-
-    if (!from || !to) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-    return SECFailure;
-    }
-    if (!len) {
-        len = PL_strlen(from);
-    }
-    if (len >= 4 && !PL_strncasecmp(from, OIDstring, 4)) {
-        from += 4; /* skip leading "OID." if present */
-    len  -= 4;
-    }
-    if (!len) {
-bad_data:
-        PORT_SetError(SEC_ERROR_BAD_DATA);
-    return SECFailure;
-    }
-    do {
-    PRUint32 decimal = 0;
-        while (len > 0 && rtl::isAsciiDigit(static_cast<unsigned char>(*from))) {
-        PRUint32 addend = (*from++ - '0');
-        --len;
-        if (decimal > max_decimal)  /* overflow */
-            goto bad_data;
-        decimal = (decimal * 10) + addend;
-        if (decimal < addend)   /* overflow */
-        goto bad_data;
-    }
-    if (len != 0 && *from != '.') {
-        goto bad_data;
-    }
-    if (decimal_numbers == 0) {
-        if (decimal > 2)
-            goto bad_data;
-        result[0] = decimal * 40;
-        result_bytes = 1;
-    } else if (decimal_numbers == 1) {
-        if (decimal > 40)
-            goto bad_data;
-        result[0] += decimal;
-    } else {
-        /* encode the decimal number,  */
-        PRUint8 * rp;
-        PRUint32 num_bytes = 0;
-        PRUint32 tmp = decimal;
-        while (tmp) {
-            num_bytes++;
-        tmp >>= 7;
-        }
-        if (!num_bytes )
-            ++num_bytes;  /* use one byte for a zero value */
-        if (num_bytes + result_bytes > sizeof result)
-            goto bad_data;
-        tmp = num_bytes;
-        rp = result + result_bytes - 1;
-        rp[tmp] = (PRUint8)(decimal & 0x7f);
-        decimal >>= 7;
-        while (--tmp > 0) {
-        rp[tmp] = (PRUint8)(decimal | 0x80);
-        decimal >>= 7;
-        }
-        result_bytes += num_bytes;
-    }
-    ++decimal_numbers;
-    if (len > 0) { /* skip trailing '.' */
-        ++from;
-        --len;
-    }
-    } while (len > 0);
-    /* now result contains result_bytes of data */
-    if (to->data && to->len >= result_bytes) {
-        PORT_Memcpy(to->data, result, to->len = result_bytes);
-    rv = SECSuccess;
-    } else {
-        SECItem result_item = {siBuffer, nullptr, 0 };
-    result_item.data = result;
-    result_item.len  = result_bytes;
-    rv = SECITEM_CopyItem(nullptr, to, &result_item);
-    }
-    return rv;
-}
-
-NSSCMSAttribute *
-my_NSS_CMSAttributeArray_FindAttrByOidTag(NSSCMSAttribute **attrs, SECOidTag oidtag, PRBool only)
-{
-    SECOidData *oid;
-    NSSCMSAttribute *attr1, *attr2;
-
-    if (attrs == nullptr)
-        return nullptr;
-
-    oid = SECOID_FindOIDByTag(oidtag);
-    if (oid == nullptr)
-        return nullptr;
-
-    while ((attr1 = *attrs++) != nullptr) {
-    if (attr1->type.len == oid->oid.len && PORT_Memcmp (attr1->type.data,
-                                oid->oid.data,
-                                oid->oid.len) == 0)
-        break;
-    }
-
-    if (attr1 == nullptr)
-        return nullptr;
-
-    if (!only)
-        return attr1;
-
-    while ((attr2 = *attrs++) != nullptr) {
-    if (attr2->type.len == oid->oid.len && PORT_Memcmp (attr2->type.data,
-                                oid->oid.data,
-                                oid->oid.len) == 0)
-        break;
-    }
-
-    if (attr2 != nullptr)
-        return nullptr;
-
-    return attr1;
-}
-
-SECStatus
-my_NSS_CMSArray_Add(PLArenaPool *poolp, void ***array, void *obj)
-{
-    int n = 0;
-    void **dest;
-
-    PORT_Assert(array != NULL);
-    if (array == nullptr)
-        return SECFailure;
-
-    if (*array == nullptr) {
-        dest = static_cast<void **>(PORT_ArenaAlloc(poolp, 2 * sizeof(void *)));
-    } else {
-        void **p = *array;
-        while (*p++)
-            n++;
-        dest = static_cast<void **>(PORT_ArenaGrow (poolp,
-                      *array,
-                      (n + 1) * sizeof(void *),
-                      (n + 2) * sizeof(void *)));
-    }
-
-    if (dest == nullptr)
-        return SECFailure;
-
-    dest[n] = obj;
-    dest[n+1] = nullptr;
-    *array = dest;
-    return SECSuccess;
-}
-
-SECOidTag
-my_NSS_CMSAttribute_GetType(NSSCMSAttribute *attr)
-{
-    SECOidData *typetag;
-
-    typetag = SECOID_FindOID(&(attr->type));
-    if (typetag == nullptr)
-        return SEC_OID_UNKNOWN;
-
-    return typetag->offset;
-}
-
-SECStatus
-my_NSS_CMSAttributeArray_AddAttr(PLArenaPool *poolp, NSSCMSAttribute ***attrs, NSSCMSAttribute *attr)
-{
-    NSSCMSAttribute *oattr;
-    void *mark;
-    SECOidTag type;
-
-    mark = PORT_ArenaMark(poolp);
-
-    /* find oidtag of attr */
-    type = my_NSS_CMSAttribute_GetType(attr);
-
-    /* see if we have one already */
-    oattr = my_NSS_CMSAttributeArray_FindAttrByOidTag(*attrs, type, PR_FALSE);
-    PORT_Assert (oattr == NULL);
-    if (oattr != nullptr)
-        goto loser; /* XXX or would it be better to replace it? */
-
-    /* no, shove it in */
-    if (my_NSS_CMSArray_Add(poolp, reinterpret_cast<void ***>(attrs), static_cast<void *>(attr)) != SECSuccess)
-        goto loser;
-
-    PORT_ArenaUnmark(poolp, mark);
-    return SECSuccess;
-
-loser:
-    PORT_ArenaRelease(poolp, mark);
-    return SECFailure;
-}
-
-SECStatus
-my_NSS_CMSSignerInfo_AddUnauthAttr(NSSCMSSignerInfo *signerinfo, NSSCMSAttribute *attr)
-{
-    return my_NSS_CMSAttributeArray_AddAttr(signerinfo->cmsg->poolp, &(signerinfo->unAuthAttr), attr);
-}
-
-SECStatus
-my_NSS_CMSSignerInfo_AddAuthAttr(NSSCMSSignerInfo *signerinfo, NSSCMSAttribute *attr)
-{
-    return my_NSS_CMSAttributeArray_AddAttr(signerinfo->cmsg->poolp, &(signerinfo->authAttr), attr);
-}
-
-NSSCMSMessage *CreateCMSMessage(const PRTime* time,
-                                NSSCMSSignedData **cms_sd,
-                                NSSCMSSignerInfo **cms_signer,
-                                CERTCertificate *cert,
-                                SECItem *digest)
-{
-    NSSCMSMessage *result = NSS_CMSMessage_Create(nullptr);
-    if (!result)
-    {
-        SAL_WARN("vcl.pdfwriter", "NSS_CMSMessage_Create failed");
-        return nullptr;
-    }
-
-    *cms_sd = NSS_CMSSignedData_Create(result);
-    if (!*cms_sd)
-    {
-        SAL_WARN("vcl.pdfwriter", "NSS_CMSSignedData_Create failed");
-        NSS_CMSMessage_Destroy(result);
-        return nullptr;
-    }
-
-    NSSCMSContentInfo *cms_cinfo = NSS_CMSMessage_GetContentInfo(result);
-    if (NSS_CMSContentInfo_SetContent_SignedData(result, cms_cinfo, *cms_sd) != SECSuccess)
-    {
-        SAL_WARN("vcl.pdfwriter", "NSS_CMSContentInfo_SetContent_SignedData failed");
-        NSS_CMSSignedData_Destroy(*cms_sd);
-        NSS_CMSMessage_Destroy(result);
-        return nullptr;
-    }
-
-    cms_cinfo = NSS_CMSSignedData_GetContentInfo(*cms_sd);
-
-    // Attach NULL data as detached data
-    if (NSS_CMSContentInfo_SetContent_Data(result, cms_cinfo, nullptr, PR_TRUE) != SECSuccess)
-    {
-        SAL_WARN("vcl.pdfwriter", "NSS_CMSContentInfo_SetContent_Data failed");
-        NSS_CMSSignedData_Destroy(*cms_sd);
-        NSS_CMSMessage_Destroy(result);
-        return nullptr;
-    }
-
-    *cms_signer = NSS_CMSSignerInfo_Create(result, cert, SEC_OID_SHA256);
-    if (!*cms_signer)
-    {
-        SAL_WARN("vcl.pdfwriter", "NSS_CMSSignerInfo_Create failed");
-        NSS_CMSSignedData_Destroy(*cms_sd);
-        NSS_CMSMessage_Destroy(result);
-        return nullptr;
-    }
-
-    if (time && NSS_CMSSignerInfo_AddSigningTime(*cms_signer, *time) != SECSuccess)
-    {
-        SAL_WARN("vcl.pdfwriter", "NSS_CMSSignerInfo_AddSigningTime failed");
-        NSS_CMSSignedData_Destroy(*cms_sd);
-        NSS_CMSMessage_Destroy(result);
-        return nullptr;
-    }
-
-    if (NSS_CMSSignerInfo_IncludeCerts(*cms_signer, NSSCMSCM_CertChain, certUsageEmailSigner) != SECSuccess)
-    {
-        SAL_WARN("vcl.pdfwriter", "NSS_CMSSignerInfo_IncludeCerts failed");
-        NSS_CMSSignedData_Destroy(*cms_sd);
-        NSS_CMSMessage_Destroy(result);
-        return nullptr;
-    }
-
-    if (NSS_CMSSignedData_AddCertificate(*cms_sd, cert) != SECSuccess)
-    {
-        SAL_WARN("vcl.pdfwriter", "NSS_CMSSignedData_AddCertificate failed");
-        NSS_CMSSignedData_Destroy(*cms_sd);
-        NSS_CMSMessage_Destroy(result);
-        return nullptr;
-    }
-
-    if (NSS_CMSSignedData_AddSignerInfo(*cms_sd, *cms_signer) != SECSuccess)
-    {
-        SAL_WARN("vcl.pdfwriter", "NSS_CMSSignedData_AddSignerInfo failed");
-        NSS_CMSSignedData_Destroy(*cms_sd);
-        NSS_CMSMessage_Destroy(result);
-        return nullptr;
-    }
-
-    if (NSS_CMSSignedData_SetDigestValue(*cms_sd, SEC_OID_SHA256, digest) != SECSuccess)
-    {
-        SAL_WARN("vcl.pdfwriter", "NSS_CMSSignedData_SetDigestValue failed");
-        NSS_CMSSignedData_Destroy(*cms_sd);
-        NSS_CMSMessage_Destroy(result);
-        return nullptr;
-    }
-
-    return result;
-}
-
-} // anonymous namespace
-
-#endif // HAVE_FEATURE_NSS && !defined(_WIN32)
-
-#ifdef _WIN32
-
-namespace
-{
-
-/// Counts how many bytes are needed to encode a given length.
-size_t GetDERLengthOfLength(size_t nLength)
-{
-    size_t nRet = 1;
-
-    if(nLength > 127)
-    {
-        while (nLength >> (nRet * 8))
-            ++nRet;
-        // Long form means one additional byte: the length of the length and
-        // the length itself.
-        ++nRet;
-    }
-    return nRet;
-}
-
-/// Writes the length part of the header.
-void WriteDERLength(SvStream& rStream, size_t nLength)
-{
-    size_t nLengthOfLength = GetDERLengthOfLength(nLength);
-    if (nLengthOfLength == 1)
-    {
-        // We can use the short form.
-        rStream.WriteUInt8(nLength);
-        return;
-    }
-
-    // 0x80 means that the we use the long form: the first byte is the length
-    // of length with the highest bit set to 1, not the actual length.
-    rStream.WriteUInt8(0x80 | (nLengthOfLength - 1));
-    for (size_t i = 1; i < nLengthOfLength; ++i)
-        rStream.WriteUInt8(nLength >> ((nLengthOfLength - i - 1) * 8));
-}
-
-const unsigned nASN1_INTEGER = 0x02;
-const unsigned nASN1_OCTET_STRING = 0x04;
-const unsigned nASN1_NULL = 0x05;
-const unsigned nASN1_OBJECT_IDENTIFIER = 0x06;
-const unsigned nASN1_SEQUENCE = 0x10;
-/// An explicit tag on a constructed value.
-const unsigned nASN1_TAGGED_CONSTRUCTED = 0xa0;
-const unsigned nASN1_CONSTRUCTED = 0x20;
-
-/// Create payload for the 'signing-certificate' signed attribute.
-bool CreateSigningCertificateAttribute(vcl::PDFWriter::PDFSignContext& rContext, PCCERT_CONTEXT pCertContext, SvStream& rEncodedCertificate)
-{
-    // CryptEncodeObjectEx() does not support encoding arbitrary ASN.1
-    // structures, like SigningCertificateV2 from RFC 5035, so let's build it
-    // manually.
-
-    // Count the certificate hash and put it to aHash.
-    // 2.16.840.1.101.3.4.2.1, i.e. sha256.
-    std::vector<unsigned char> aSHA256{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01};
-
-    HCRYPTPROV hProv = 0;
-    if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
-    {
-        SAL_WARN("vcl.pdfwriter", "CryptAcquireContext() failed");
-        return false;
-    }
-
-    HCRYPTHASH hHash = 0;
-    if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash))
-    {
-        SAL_WARN("vcl.pdfwriter", "CryptCreateHash() failed");
-        return false;
-    }
-
-    if (!CryptHashData(hHash, reinterpret_cast<const BYTE*>(rContext.m_pDerEncoded), rContext.m_nDerEncoded, 0))
-    {
-        SAL_WARN("vcl.pdfwriter", "CryptHashData() failed");
-        return false;
-    }
-
-    DWORD nHash = 0;
-    if (!CryptGetHashParam(hHash, HP_HASHVAL, nullptr, &nHash, 0))
-    {
-        SAL_WARN("vcl.pdfwriter", "CryptGetHashParam() failed to provide the hash length");
-        return false;
-    }
-
-    std::vector<unsigned char> aHash(nHash);
-    if (!CryptGetHashParam(hHash, HP_HASHVAL, aHash.data(), &nHash, 0))
-    {
-        SAL_WARN("vcl.pdfwriter", "CryptGetHashParam() failed to provide the hash");
-        return false;
-    }
-
-    CryptDestroyHash(hHash);
-    CryptReleaseContext(hProv, 0);
-
-    // Collect info for IssuerSerial.
-    BYTE* pIssuer = pCertContext->pCertInfo->Issuer.pbData;
-    DWORD nIssuer = pCertContext->pCertInfo->Issuer.cbData;
-    BYTE* pSerial = pCertContext->pCertInfo->SerialNumber.pbData;
-    DWORD nSerial = pCertContext->pCertInfo->SerialNumber.cbData;
-    // pSerial is LE, aSerial is BE.
-    std::vector<BYTE> aSerial(nSerial);
-    for (size_t i = 0; i < nSerial; ++i)
-        aSerial[i] = *(pSerial + nSerial - i - 1);
-
-    // We now have all the info to count the lengths.
-    // The layout of the payload is:
-    // SEQUENCE: SigningCertificateV2
-    //     SEQUENCE: SEQUENCE OF ESSCertIDv2
-    //         SEQUENCE: ESSCertIDv2
-    //             SEQUENCE: AlgorithmIdentifier
-    //                 OBJECT: algorithm
-    //                 NULL: parameters
-    //             OCTET STRING: certHash
-    //             SEQUENCE: IssuerSerial
-    //                 SEQUENCE: GeneralNames
-    //                     cont [ 4 ]: Name
-    //                         SEQUENCE: Issuer blob
-    //                 INTEGER: CertificateSerialNumber
-
-    size_t nAlgorithm = 1 + GetDERLengthOfLength(aSHA256.size()) + aSHA256.size();
-    size_t nParameters = 1 + GetDERLengthOfLength(1);
-    size_t nAlgorithmIdentifier = 1 + GetDERLengthOfLength(nAlgorithm + nParameters) + nAlgorithm + nParameters;
-    size_t nCertHash = 1 + GetDERLengthOfLength(aHash.size()) + aHash.size();
-    size_t nName = 1 + GetDERLengthOfLength(nIssuer) + nIssuer;
-    size_t nGeneralNames = 1 + GetDERLengthOfLength(nName) + nName;
-    size_t nCertificateSerialNumber = 1 + GetDERLengthOfLength(nSerial) + nSerial;
-    size_t nIssuerSerial = 1 + GetDERLengthOfLength(nGeneralNames + nCertificateSerialNumber) + nGeneralNames + nCertificateSerialNumber;
-    size_t nESSCertIDv2 = 1 + GetDERLengthOfLength(nAlgorithmIdentifier + nCertHash + nIssuerSerial) + nAlgorithmIdentifier + nCertHash + nIssuerSerial;
-    size_t nESSCertIDv2s = 1 + GetDERLengthOfLength(nESSCertIDv2) + nESSCertIDv2;
-
-    // Write SigningCertificateV2.
-    rEncodedCertificate.WriteUInt8(nASN1_SEQUENCE | nASN1_CONSTRUCTED);
-    WriteDERLength(rEncodedCertificate, nESSCertIDv2s);
-    // Write SEQUENCE OF ESSCertIDv2.
-    rEncodedCertificate.WriteUInt8(nASN1_SEQUENCE | nASN1_CONSTRUCTED);
-    WriteDERLength(rEncodedCertificate, nESSCertIDv2);
-    // Write ESSCertIDv2.
-    rEncodedCertificate.WriteUInt8(nASN1_SEQUENCE | nASN1_CONSTRUCTED);
-    WriteDERLength(rEncodedCertificate, nAlgorithmIdentifier + nCertHash + nIssuerSerial);
-    // Write AlgorithmIdentifier.
-    rEncodedCertificate.WriteUInt8(nASN1_SEQUENCE | nASN1_CONSTRUCTED);
-    WriteDERLength(rEncodedCertificate, nAlgorithm + nParameters);
-    // Write algorithm.
-    rEncodedCertificate.WriteUInt8(nASN1_OBJECT_IDENTIFIER);
-    WriteDERLength(rEncodedCertificate, aSHA256.size());
-    rEncodedCertificate.WriteBytes(aSHA256.data(), aSHA256.size());
-    // Write parameters.
-    rEncodedCertificate.WriteUInt8(nASN1_NULL);
-    rEncodedCertificate.WriteUInt8(0);
-    // Write certHash.
-    rEncodedCertificate.WriteUInt8(nASN1_OCTET_STRING);
-    WriteDERLength(rEncodedCertificate, aHash.size());
-    rEncodedCertificate.WriteBytes(aHash.data(), aHash.size());
-    // Write IssuerSerial.
-    rEncodedCertificate.WriteUInt8(nASN1_SEQUENCE | nASN1_CONSTRUCTED);
-    WriteDERLength(rEncodedCertificate, nGeneralNames + nCertificateSerialNumber);
-    // Write GeneralNames.
-    rEncodedCertificate.WriteUInt8(nASN1_SEQUENCE | nASN1_CONSTRUCTED);
-    WriteDERLength(rEncodedCertificate, nName);
-    // Write Name.
-    rEncodedCertificate.WriteUInt8(nASN1_TAGGED_CONSTRUCTED | 4);
-    WriteDERLength(rEncodedCertificate, nIssuer);
-    rEncodedCertificate.WriteBytes(pIssuer, nIssuer);
-    // Write CertificateSerialNumber.
-    rEncodedCertificate.WriteUInt8(nASN1_INTEGER);
-    WriteDERLength(rEncodedCertificate, nSerial);
-    rEncodedCertificate.WriteBytes(aSerial.data(), aSerial.size());
-
-    return true;
-}
-} // anonymous namespace
-
-#endif
-
-bool PDFWriter::Sign(PDFSignContext& rContext)
-{
-#ifndef _WIN32
-
-    CERTCertificate *cert = CERT_DecodeCertFromPackage(reinterpret_cast<char *>(rContext.m_pDerEncoded), rContext.m_nDerEncoded);
-
-    if (!cert)
-    {
-        SAL_WARN("vcl.pdfwriter", "CERT_DecodeCertFromPackage failed");
-        return false;
-    }
-
-    std::vector<unsigned char> aHashResult;
-    {
-        comphelper::Hash aHash(comphelper::HashType::SHA256);
-
-        aHash.update(static_cast<const unsigned char*>(rContext.m_pByteRange1), rContext.m_nByteRange1);
-
-        aHash.update(static_cast<const unsigned char*>(rContext.m_pByteRange2), rContext.m_nByteRange2);
-
-        aHashResult = aHash.finalize();
-    }
-    SECItem digest;
-    digest.data = aHashResult.data();
-    digest.len = aHashResult.size();
-
-#ifdef DBG_UTIL
-    {
-        FILE *out = fopen("PDFWRITER.hash.data", "wb");
-        fwrite(aHashResult.data(), SHA256_LENGTH, 1, out);
-        fclose(out);
-    }
-#endif
-
-    PRTime now = PR_Now();
-    NSSCMSSignedData *cms_sd;
-    NSSCMSSignerInfo *cms_signer;
-    NSSCMSMessage *cms_msg = CreateCMSMessage(nullptr, &cms_sd, &cms_signer, cert, &digest);
-    if (!cms_msg)
-        return false;
-
-    OString pass(OUStringToOString( rContext.m_aSignPassword, RTL_TEXTENCODING_UTF8 ));
-
-    TimeStampReq src;
-    OStringBuffer response_buffer;
-    TimeStampResp response;
-    SECItem response_item;
-    NSSCMSAttribute timestamp;
-    SECItem values[2];
-    SECItem *valuesp[2];
-    valuesp[0] = values;
-    valuesp[1] = nullptr;
-    SECOidData typetag;
-
-    if( !rContext.m_aSignTSA.isEmpty() )
-    {
-        // Create another CMS message with the same contents as cms_msg, because it doesn't seem
-        // possible to encode a message twice (once to get something to timestamp, and then after
-        // adding the timestamp attribute).
-
-        NSSCMSSignedData *ts_cms_sd;
-        NSSCMSSignerInfo *ts_cms_signer;
-        NSSCMSMessage *ts_cms_msg = CreateCMSMessage(&now, &ts_cms_sd, &ts_cms_signer, cert, &digest);
-        if (!ts_cms_msg)
-        {
-            return false;
-        }
-
-        SECItem ts_cms_output;
-        ts_cms_output.data = nullptr;
-        ts_cms_output.len = 0;
-        PLArenaPool *ts_arena = PORT_NewArena(10000);
-        NSSCMSEncoderContext *ts_cms_ecx;
-        ts_cms_ecx = NSS_CMSEncoder_Start(ts_cms_msg, nullptr, nullptr, &ts_cms_output, ts_arena, PDFSigningPKCS7PasswordCallback,
-                                          const_cast<sal_Char*>(pass.getStr()), nullptr, nullptr, nullptr, nullptr);
-
-        if (NSS_CMSEncoder_Finish(ts_cms_ecx) != SECSuccess)
-        {
-            SAL_WARN("vcl.pdfwriter", "NSS_CMSEncoder_Finish failed");
-            return false;
-        }
-
-        // I have compared the ts_cms_output produced here with the cms_output produced below, with
-        // the DONTCALLADDUNAUTHATTR env var set (i.e. without actually calling
-        // my_NSS_CMSSignerInfo_AddUnauthAttr()), and they are identical.
-
-#ifdef DBG_UTIL
-        {
-            FILE *out = fopen("PDFWRITER.ts_cms.data", "wb");
-            fwrite(ts_cms_output.data, ts_cms_output.len, 1, out);
-            fclose(out);
-        }
-#endif
-
-        std::vector<unsigned char> aTsHashResult = comphelper::Hash::calculateHash(ts_cms_signer->encDigest.data, ts_cms_signer->encDigest.len, comphelper::HashType::SHA256);
-        SECItem ts_digest;
-        ts_digest.type = siBuffer;
-        ts_digest.data = aTsHashResult.data();
-        ts_digest.len = aTsHashResult.size();
-
-#ifdef DBG_UTIL
-        {
-            FILE *out = fopen("PDFWRITER.ts_hash.data", "wb");
-            fwrite(aTsHashResult.data(), SHA256_LENGTH, 1, out);
-            fclose(out);
-        }
-#endif
-
-        unsigned char cOne = 1;
-        src.version.type = siUnsignedInteger;
-        src.version.data = &cOne;
-        src.version.len = sizeof(cOne);
-
-        src.messageImprint.hashAlgorithm.algorithm.data = nullptr;
-        src.messageImprint.hashAlgorithm.parameters.data = nullptr;
-        SECOID_SetAlgorithmID(nullptr, &src.messageImprint.hashAlgorithm, SEC_OID_SHA256, nullptr);
-        src.messageImprint.hashedMessage = ts_digest;
-
-        src.reqPolicy.type = siBuffer;
-        src.reqPolicy.data = nullptr;
-        src.reqPolicy.len = 0;
-
-        unsigned int nNonce = comphelper::rng::uniform_uint_distribution(0, SAL_MAX_UINT32);
-        src.nonce.type = siUnsignedInteger;
-        src.nonce.data = reinterpret_cast<unsigned char*>(&nNonce);
-        src.nonce.len = sizeof(nNonce);
-
-        src.certReq.type = siUnsignedInteger;
-        src.certReq.data = &cOne;
-        src.certReq.len = sizeof(cOne);
-
-        src.extensions = nullptr;
-
-        SECItem* timestamp_request = SEC_ASN1EncodeItem(nullptr, nullptr, &src, TimeStampReq_Template);
-        if (timestamp_request == nullptr)
-        {
-            SAL_WARN("vcl.pdfwriter", "SEC_ASN1EncodeItem failed");
-            return false;
-        }
-
-        if (timestamp_request->data == nullptr)
-        {
-            SAL_WARN("vcl.pdfwriter", "SEC_ASN1EncodeItem succeeded but got NULL data");
-            SECITEM_FreeItem(timestamp_request, PR_TRUE);
-            return false;
-        }
-
-        SAL_INFO("vcl.pdfwriter", "request length=" << timestamp_request->len);
-
-#ifdef DBG_UTIL
-        {
-            FILE *out = fopen("PDFWRITER.timestampreq.data", "wb");
-            fwrite(timestamp_request->data, timestamp_request->len, 1, out);
-            fclose(out);
-        }
-#endif
-
-        // Send time stamp request to TSA server, receive response
-
-        CURL* curl = curl_easy_init();
-        CURLcode rc;
-        struct curl_slist* slist = nullptr;
-
-        if (!curl)
-        {
-            SAL_WARN("vcl.pdfwriter", "curl_easy_init failed");
-            SECITEM_FreeItem(timestamp_request, PR_TRUE);
-            return false;
-        }
-
-        SAL_INFO("vcl.pdfwriter", "Setting curl to verbose: " << (curl_easy_setopt(curl, CURLOPT_VERBOSE, 1) == CURLE_OK ? "OK" : "FAIL"));
-
-        if ((rc = curl_easy_setopt(curl, CURLOPT_URL, OUStringToOString(rContext.m_aSignTSA, RTL_TEXTENCODING_UTF8).getStr())) != CURLE_OK)
-        {
-            SAL_WARN("vcl.pdfwriter", "curl_easy_setopt(CURLOPT_URL) failed: " << curl_easy_strerror(rc));
-            curl_easy_cleanup(curl);
-            SECITEM_FreeItem(timestamp_request, PR_TRUE);
-            return false;
-        }
-
-        slist = curl_slist_append(slist, "Content-Type: application/timestamp-query");
-        slist = curl_slist_append(slist, "Accept: application/timestamp-reply");
-
-        if ((rc = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist)) != CURLE_OK)
-        {
-            SAL_WARN("vcl.pdfwriter", "curl_easy_setopt(CURLOPT_HTTPHEADER) failed: " << curl_easy_strerror(rc));
-            curl_slist_free_all(slist);
-            curl_easy_cleanup(curl);
-            SECITEM_FreeItem(timestamp_request, PR_TRUE);
-            return false;
-        }
-
-        if ((rc = curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, static_cast<long>(timestamp_request->len))) != CURLE_OK ||
-            (rc = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, timestamp_request->data)) != CURLE_OK)
-        {
-            SAL_WARN("vcl.pdfwriter", "curl_easy_setopt(CURLOPT_POSTFIELDSIZE or CURLOPT_POSTFIELDS) failed: " << curl_easy_strerror(rc));
-            curl_easy_cleanup(curl);
-            SECITEM_FreeItem(timestamp_request, PR_TRUE);
-            return false;
-        }
-
-        if ((rc = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_buffer)) != CURLE_OK ||
-            (rc = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, AppendToBuffer)) != CURLE_OK)
-        {
-            SAL_WARN("vcl.pdfwriter", "curl_easy_setopt(CURLOPT_WRITEDATA or CURLOPT_WRITEFUNCTION) failed: " << curl_easy_strerror(rc));
-            curl_easy_cleanup(curl);
-            SECITEM_FreeItem(timestamp_request, PR_TRUE);
-            return false;
-        }
-
-        if ((rc = curl_easy_setopt(curl, CURLOPT_POST, 1)) != CURLE_OK)
-        {
-            SAL_WARN("vcl.pdfwriter", "curl_easy_setopt(CURLOPT_POST) failed: " << curl_easy_strerror(rc));
-            curl_easy_cleanup(curl);
-            SECITEM_FreeItem(timestamp_request, PR_TRUE);
-            return false;
-        }
-
-        char error_buffer[CURL_ERROR_SIZE];
-        if ((rc = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer)) != CURLE_OK)
-        {
-            SAL_WARN("vcl.pdfwriter", "curl_easy_setopt(CURLOPT_ERRORBUFFER) failed: " << curl_easy_strerror(rc));
-            curl_easy_cleanup(curl);
-            SECITEM_FreeItem(timestamp_request, PR_TRUE);
-            return false;
-        }
-
-        // Use a ten second timeout
-        if ((rc = curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10)) != CURLE_OK ||
-            (rc = curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10)) != CURLE_OK)
-        {
-            SAL_WARN("vcl.pdfwriter", "curl_easy_setopt(CURLOPT_TIMEOUT or CURLOPT_CONNECTTIMEOUT) failed: " << curl_easy_strerror(rc));
-            curl_easy_cleanup(curl);
-            SECITEM_FreeItem(timestamp_request, PR_TRUE);
-            return false;
-        }
-
-        if (curl_easy_perform(curl) != CURLE_OK)
-        {
-            SAL_WARN("vcl.pdfwriter", "curl_easy_perform failed: " << error_buffer);
-            curl_easy_cleanup(curl);
-            SECITEM_FreeItem(timestamp_request, PR_TRUE);
-            return false;
-        }
-
-        SAL_INFO("vcl.pdfwriter", "PDF signing: got response, length=" << response_buffer.getLength());
-
-#ifdef DBG_UTIL
-        {
-            FILE *out = fopen("PDFWRITER.reply.data", "wb");
-            fwrite(response_buffer.getStr(), response_buffer.getLength(), 1, out);
-            fclose(out);
-        }
-#endif
-
-        curl_slist_free_all(slist);
-        curl_easy_cleanup(curl);
-        SECITEM_FreeItem(timestamp_request, PR_TRUE);
-
-        memset(&response, 0, sizeof(response));
-
-        response_item.type = siBuffer;
-        response_item.data = reinterpret_cast<unsigned char*>(const_cast<char*>(response_buffer.getStr()));
-        response_item.len = response_buffer.getLength();
-
-        if (SEC_ASN1DecodeItem(nullptr, &response, TimeStampResp_Template, &response_item) != SECSuccess)
-        {
-            SAL_WARN("vcl.pdfwriter", "SEC_ASN1DecodeItem failed");
-            return false;
-        }
-
-        SAL_INFO("vcl.pdfwriter", "TimeStampResp received and decoded, status=" << PKIStatusInfoToString(response.status));
-
-        if (response.status.status.len != 1 ||
-            (response.status.status.data[0] != 0 && response.status.status.data[0] != 1))
-        {
-            SAL_WARN("vcl.pdfwriter", "Timestamp request was not granted");
-            return false;
-        }
-
-        // timestamp.type filled in below
-
-        // Not sure if we actually need two entries in the values array, now when valuesp is an
-        // array too, the pointer to the values array followed by a null pointer. But I don't feel
-        // like experimenting.
-        values[0] = response.timeStampToken;
-        values[1].type = siBuffer;
-        values[1].data = nullptr;
-        values[1].len = 0;
-
-        timestamp.values = valuesp;
-
-        typetag.oid.data = nullptr;
-        // id-aa-timeStampToken OBJECT IDENTIFIER ::= { iso(1)
-        // member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)
-        // smime(16) aa(2) 14 }
-        if (my_SEC_StringToOID(&typetag.oid, "1.2.840.113549.1.9.16.2.14", 0) != SECSuccess)
-        {
-            SAL_WARN("vcl.pdfwriter", "SEC_StringToOID failed");
-            return false;
-        }
-        typetag.offset = SEC_OID_UNKNOWN; // ???
-        typetag.desc = "id-aa-timeStampToken";
-        typetag.mechanism = CKM_SHA_1; // ???
-        typetag.supportedExtension = UNSUPPORTED_CERT_EXTENSION; // ???
-        timestamp.typeTag = &typetag;
-
-        timestamp.type = typetag.oid; // ???
-
-        timestamp.encoded = PR_TRUE; // ???
-
-#ifdef DBG_UTIL
-        if (getenv("DONTCALLADDUNAUTHATTR"))
-            ;
-        else
-#endif
-        if (my_NSS_CMSSignerInfo_AddUnauthAttr(cms_signer, &timestamp) != SECSuccess)
-        {
-            SAL_WARN("vcl.pdfwriter", "NSS_CMSSignerInfo_AddUnauthAttr failed");
-            return false;
-        }
-    }
-
-    // Add the signing certificate as a signed attribute.
-    ESSCertIDv2* aCertIDs[2];
-    ESSCertIDv2 aCertID;
-    // Write ESSCertIDv2.hashAlgorithm.
-    aCertID.hashAlgorithm.algorithm.data = nullptr;
-    aCertID.hashAlgorithm.parameters.data = nullptr;
-    SECOID_SetAlgorithmID(nullptr, &aCertID.hashAlgorithm, SEC_OID_SHA256, nullptr);
-    // Write ESSCertIDv2.certHash.
-    SECItem aCertHashItem;
-    auto pDerEncoded = reinterpret_cast<const unsigned char *>(rContext.m_pDerEncoded);
-    std::vector<unsigned char> aCertHashResult = comphelper::Hash::calculateHash(pDerEncoded, rContext.m_nDerEncoded, comphelper::HashType::SHA256);
-    aCertHashItem.type = siBuffer;
-    aCertHashItem.data = aCertHashResult.data();
-    aCertHashItem.len = aCertHashResult.size();
-    aCertID.certHash = aCertHashItem;
-    // Write ESSCertIDv2.issuerSerial.
-    IssuerSerial aSerial;
-    GeneralName aName;
-    aName.name = cert->issuer;
-    aSerial.issuer.names = aName;
-    aSerial.serialNumber = cert->serialNumber;
-    aCertID.issuerSerial = aSerial;
-    // Write SigningCertificateV2.certs.
-    aCertIDs[0] = &aCertID;
-    aCertIDs[1] = nullptr;
-    SigningCertificateV2 aCertificate;
-    aCertificate.certs = &aCertIDs[0];
-    SECItem* pEncodedCertificate = SEC_ASN1EncodeItem(nullptr, nullptr, &aCertificate, SigningCertificateV2Template);
-    if (!pEncodedCertificate)
-    {
-        SAL_WARN("vcl.pdfwriter", "SEC_ASN1EncodeItem() failed");
-        return false;
-    }
-
-    NSSCMSAttribute aAttribute;
-    SECItem aAttributeValues[2];
-    SECItem* pAttributeValues[2];
-    pAttributeValues[0] = aAttributeValues;
-    pAttributeValues[1] = nullptr;
-    aAttributeValues[0] = *pEncodedCertificate;
-    aAttributeValues[1].type = siBuffer;
-    aAttributeValues[1].data = nullptr;
-    aAttributeValues[1].len = 0;
-    aAttribute.values = pAttributeValues;
-
-    SECOidData aOidData;
-    aOidData.oid.data = nullptr;
-    /*
-     * id-aa-signingCertificateV2 OBJECT IDENTIFIER ::=
-     * { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
-     *   smime(16) id-aa(2) 47 }
-     */
-    if (my_SEC_StringToOID(&aOidData.oid, "1.2.840.113549.1.9.16.2.47", 0) != SECSuccess)
-    {
-        SAL_WARN("vcl.pdfwriter", "my_SEC_StringToOID() failed");
-        return false;
-    }
-    aOidData.offset = SEC_OID_UNKNOWN;
-    aOidData.desc = "id-aa-signingCertificateV2";
-    aOidData.mechanism = CKM_SHA_1;
-    aOidData.supportedExtension = UNSUPPORTED_CERT_EXTENSION;
-    aAttribute.typeTag = &aOidData;
-    aAttribute.type = aOidData.oid;
-    aAttribute.encoded = PR_TRUE;
-
-    if (my_NSS_CMSSignerInfo_AddAuthAttr(cms_signer, &aAttribute) != SECSuccess)
-    {
-        SAL_WARN("vcl.pdfwriter", "my_NSS_CMSSignerInfo_AddAuthAttr() failed");
-        return false;
-    }
-
-    SECItem cms_output;
-    cms_output.data = nullptr;
-    cms_output.len = 0;
-    PLArenaPool *arena = PORT_NewArena(10000);
-    NSSCMSEncoderContext *cms_ecx;
-
-    // Possibly it would work to even just pass NULL for the password callback function and its
-    // argument here. After all, at least with the hardware token and associated software I tested
-    // with, the software itself pops up a dialog asking for the PIN (password). But I am not going
-    // to test it and risk locking up my token...
-
-    cms_ecx = NSS_CMSEncoder_Start(cms_msg, nullptr, nullptr, &cms_output, arena, PDFSigningPKCS7PasswordCallback,
-                                   const_cast<sal_Char*>(pass.getStr()), nullptr, nullptr, nullptr, nullptr);
-
-    if (!cms_ecx)
-    {
-        SAL_WARN("vcl.pdfwriter", "NSS_CMSEncoder_Start failed");
-        return false;
-    }
-
-    if (NSS_CMSEncoder_Finish(cms_ecx) != SECSuccess)
-    {
-        SAL_WARN("vcl.pdfwriter", "NSS_CMSEncoder_Finish failed");
-        return false;
-    }
-
-#ifdef DBG_UTIL
-    {
-        FILE *out = fopen("PDFWRITER.cms.data", "wb");
-        fwrite(cms_output.data, cms_output.len, 1, out);
-        fclose(out);
-    }
-#endif
-
-    if (cms_output.len*2 > MAX_SIGNATURE_CONTENT_LENGTH)
-    {
-        SAL_WARN("vcl.pdfwriter", "Signature requires more space (" << cms_output.len*2 << ") than we reserved (" << MAX_SIGNATURE_CONTENT_LENGTH << ")");
-        NSS_CMSMessage_Destroy(cms_msg);
-        return false;
-    }
-
-    for (unsigned int i = 0; i < cms_output.len ; i++)
-        appendHex(cms_output.data[i], rContext.m_rCMSHexBuffer);
-
-    SECITEM_FreeItem(pEncodedCertificate, PR_TRUE);
-    NSS_CMSMessage_Destroy(cms_msg);
-
-    return true;
-
-#else // _WIN32
-    PCCERT_CONTEXT pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, reinterpret_cast<const BYTE*>(rContext.m_pDerEncoded), rContext.m_nDerEncoded);
-    if (pCertContext == nullptr)
-    {
-        SAL_WARN("vcl.pdfwriter", "CertCreateCertificateContext failed: " << WindowsErrorString(GetLastError()));
-        return false;
-    }
-
-    CRYPT_SIGN_MESSAGE_PARA aPara;
-
-    memset(&aPara, 0, sizeof(aPara));
-    aPara.cbSize = sizeof(aPara);
-    aPara.dwMsgEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
-    aPara.pSigningCert = pCertContext;
-    aPara.HashAlgorithm.pszObjId = const_cast<LPSTR>(szOID_NIST_sha256);
-    aPara.HashAlgorithm.Parameters.cbData = 0;
-    aPara.cMsgCert = 1;
-    aPara.rgpMsgCert = &pCertContext;
-
-    HCRYPTPROV hCryptProv;
-    DWORD nKeySpec;
-    BOOL bFreeNeeded;
-
-    if (!CryptAcquireCertificatePrivateKey(pCertContext,
-                                           CRYPT_ACQUIRE_CACHE_FLAG,
-                                           nullptr,
-                                           &hCryptProv,
-                                           &nKeySpec,
-                                           &bFreeNeeded))
-    {
-        SAL_WARN("vcl.pdfwriter", "CryptAcquireCertificatePrivateKey failed: " << WindowsErrorString(GetLastError()));
-        CertFreeCertificateContext(pCertContext);
-        return false;
-    }
-    assert(!bFreeNeeded);
-
-    CMSG_SIGNER_ENCODE_INFO aSignerInfo;
-
-    memset(&aSignerInfo, 0, sizeof(aSignerInfo));
-    aSignerInfo.cbSize = sizeof(aSignerInfo);
-    aSignerInfo.pCertInfo = pCertContext->pCertInfo;
-    aSignerInfo.hCryptProv = hCryptProv;
-    aSignerInfo.dwKeySpec = nKeySpec;
-    aSignerInfo.HashAlgorithm.pszObjId = const_cast<LPSTR>(szOID_NIST_sha256);
-    aSignerInfo.HashAlgorithm.Parameters.cbData = 0;
-
-    // Add the signing certificate as a signed attribute.
-    CRYPT_INTEGER_BLOB aCertificateBlob;
-    SvMemoryStream aEncodedCertificate;
-    if (!CreateSigningCertificateAttribute(rContext, pCertContext, aEncodedCertificate))
-    {
-        SAL_WARN("vcl.pdfwriter", "CreateSigningCertificateAttribute() failed");
-        return false;
-    }
-    aCertificateBlob.pbData = const_cast<BYTE*>(static_cast<const BYTE*>(aEncodedCertificate.GetData()));
-    aCertificateBlob.cbData = aEncodedCertificate.GetSize();
-    CRYPT_ATTRIBUTE aCertificateAttribute;
-    /*
-     * id-aa-signingCertificateV2 OBJECT IDENTIFIER ::=
-     * { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
-     *   smime(16) id-aa(2) 47 }
-     */
-    aCertificateAttribute.pszObjId = const_cast<LPSTR>("1.2.840.113549.1.9.16.2.47");
-    aCertificateAttribute.cValue = 1;
-    aCertificateAttribute.rgValue = &aCertificateBlob;
-    aSignerInfo.cAuthAttr = 1;
-    aSignerInfo.rgAuthAttr = &aCertificateAttribute;
-
-    CMSG_SIGNED_ENCODE_INFO aSignedInfo;
-    memset(&aSignedInfo, 0, sizeof(aSignedInfo));
-    aSignedInfo.cbSize = sizeof(aSignedInfo);
-    aSignedInfo.cSigners = 1;
-    aSignedInfo.rgSigners = &aSignerInfo;
-
-    CERT_BLOB aCertBlob;
-
-    aCertBlob.cbData = pCertContext->cbCertEncoded;
-    aCertBlob.pbData = pCertContext->pbCertEncoded;
-
-    aSignedInfo.cCertEncoded = 1;
-    aSignedInfo.rgCertEncoded = &aCertBlob;
-
-    HCRYPTMSG hMsg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
-                                          CMSG_DETACHED_FLAG,
-                                          CMSG_SIGNED,
-                                          &aSignedInfo,
-                                          nullptr,
-                                          nullptr);
-    if (!hMsg)
-    {
-        SAL_WARN("vcl.pdfwriter", "CryptMsgOpenToEncode failed: " << WindowsErrorString(GetLastError()));
-        CertFreeCertificateContext(pCertContext);
-        return false;
-    }
-
-    if (!CryptMsgUpdate(hMsg, static_cast<const BYTE *>(rContext.m_pByteRange1), rContext.m_nByteRange1, FALSE) ||
-        !CryptMsgUpdate(hMsg, static_cast<const BYTE *>(rContext.m_pByteRange2), rContext.m_nByteRange2, TRUE))
-    {
-        SAL_WARN("vcl.pdfwriter", "CryptMsgUpdate failed: " << WindowsErrorString(GetLastError()));
-        CryptMsgClose(hMsg);
-        CertFreeCertificateContext(pCertContext);
-        return false;
-    }
-
-    PCRYPT_TIMESTAMP_CONTEXT pTsContext = nullptr;
-
-    if( !rContext.m_aSignTSA.isEmpty() )
-    {
-        HCRYPTMSG hDecodedMsg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
-                                                     CMSG_DETACHED_FLAG,
-                                                     CMSG_SIGNED,
-                                                     NULL,
-                                                     nullptr,
-                                                     nullptr);
-        if (!hDecodedMsg)
-        {
-            SAL_WARN("vcl.pdfwriter", "CryptMsgOpenToDecode failed: " << WindowsErrorString(GetLastError()));
-            CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
-            return false;
-        }
-
-        DWORD nTsSigLen = 0;
-
-        if (!CryptMsgGetParam(hMsg, CMSG_BARE_CONTENT_PARAM, 0, nullptr, &nTsSigLen))
-        {
-            SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_BARE_CONTENT_PARAM) failed: " << WindowsErrorString(GetLastError()));
-            CryptMsgClose(hDecodedMsg);
-            CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
-            return false;
-        }
-
-        SAL_INFO("vcl.pdfwriter", "nTsSigLen=" << nTsSigLen);
-
-        std::unique_ptr<BYTE[]> pTsSig(new BYTE[nTsSigLen]);
-
-        if (!CryptMsgGetParam(hMsg, CMSG_BARE_CONTENT_PARAM, 0, pTsSig.get(), &nTsSigLen))
-        {
-            SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_BARE_CONTENT_PARAM) failed: " << WindowsErrorString(GetLastError()));
-            CryptMsgClose(hDecodedMsg);
-            CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
-            return false;
-        }
-
-        if (!CryptMsgUpdate(hDecodedMsg, pTsSig.get(), nTsSigLen, TRUE))
-        {
-            SAL_WARN("vcl.pdfwriter", "CryptMsgUpdate failed: " << WindowsErrorString(GetLastError()));
-            CryptMsgClose(hDecodedMsg);
-            CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
-            return false;
-        }
-
-        DWORD nDecodedSignerInfoLen = 0;
-        if (!CryptMsgGetParam(hDecodedMsg, CMSG_SIGNER_INFO_PARAM, 0, nullptr, &nDecodedSignerInfoLen))
-        {
-            SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) failed: " << WindowsErrorString(GetLastError()));
-            CryptMsgClose(hDecodedMsg);
-            CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
-            return false;
-        }
-
-        std::unique_ptr<BYTE[]> pDecodedSignerInfoBuf(new BYTE[nDecodedSignerInfoLen]);
-
-        if (!CryptMsgGetParam(hDecodedMsg, CMSG_SIGNER_INFO_PARAM, 0, pDecodedSignerInfoBuf.get(), &nDecodedSignerInfoLen))
-        {
-            SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) failed: " << WindowsErrorString(GetLastError()));
-            CryptMsgClose(hDecodedMsg);
-            CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
-            return false;
-        }
-
-        CMSG_SIGNER_INFO *pDecodedSignerInfo = reinterpret_cast<CMSG_SIGNER_INFO *>(pDecodedSignerInfoBuf.get());
-
-        CRYPT_TIMESTAMP_PARA aTsPara;
-        unsigned int nNonce = comphelper::rng::uniform_uint_distribution(0, SAL_MAX_UINT32);
-
-        aTsPara.pszTSAPolicyId = nullptr;
-        aTsPara.fRequestCerts = TRUE;
-        aTsPara.Nonce.cbData = sizeof(nNonce);
-        aTsPara.Nonce.pbData = reinterpret_cast<BYTE *>(&nNonce);
-        aTsPara.cExtension = 0;
-        aTsPara.rgExtension = nullptr;
-
-        if (!CryptRetrieveTimeStamp(SAL_W(rContext.m_aSignTSA.getStr()),
-                     0,
-                     10000,
-                     szOID_NIST_sha256,
-                     &aTsPara,
-                     pDecodedSignerInfo->EncryptedHash.pbData,
-                     pDecodedSignerInfo->EncryptedHash.cbData,
-                     &pTsContext,
-                     nullptr,
-                     nullptr))
-        {
-            SAL_WARN("vcl.pdfwriter", "CryptRetrieveTimeStamp failed: " << WindowsErrorString(GetLastError()));
-            CryptMsgClose(hDecodedMsg);
-            CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
-            return false;
-        }
-
-        SAL_INFO("vcl.pdfwriter", "Time stamp size is " << pTsContext->cbEncoded << " bytes");
-
-#ifdef DBG_UTIL
-        {
-            FILE *out = fopen("PDFWRITER.tstoken.data", "wb");
-            fwrite(pTsContext->pbEncoded, pTsContext->cbEncoded, 1, out);
-            fclose(out);
-        }
-#endif
-
-        // I tried to use CryptMsgControl() with CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR to add the
-        // timestamp, but that failed with "The parameter is incorrect". Probably it is too late to
-        // modify the message once its data has already been encoded as part of the
-        // CryptMsgGetParam() with CMSG_BARE_CONTENT_PARAM above. So close the message and re-do its
-        // creation steps, but now with an amended aSignerInfo.
-
-        CRYPT_INTEGER_BLOB aTimestampBlob;
-        aTimestampBlob.cbData = pTsContext->cbEncoded;
-        aTimestampBlob.pbData = pTsContext->pbEncoded;
-
-        CRYPT_ATTRIBUTE aTimestampAttribute;
-        aTimestampAttribute.pszObjId = const_cast<LPSTR>(
-            "1.2.840.113549.1.9.16.2.14");
-        aTimestampAttribute.cValue = 1;
-        aTimestampAttribute.rgValue = &aTimestampBlob;
-
-        aSignerInfo.cUnauthAttr = 1;
-        aSignerInfo.rgUnauthAttr = &aTimestampAttribute;
-
-        CryptMsgClose(hMsg);
-
-        hMsg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
-                                    CMSG_DETACHED_FLAG,
-                                    CMSG_SIGNED,
-                                    &aSignedInfo,
-                                    nullptr,
-                                    nullptr);
-        if (!hMsg ||
-            !CryptMsgUpdate(hMsg, static_cast<const BYTE *>(rContext.m_pByteRange1), rContext.m_nByteRange1, FALSE) ||
-            !CryptMsgUpdate(hMsg, static_cast<const BYTE *>(rContext.m_pByteRange1), rContext.m_nByteRange2, TRUE))
-        {
-            SAL_WARN("vcl.pdfwriter", "Re-creating the message failed: " << WindowsErrorString(GetLastError()));
-            CryptMemFree(pTsContext);
-            CryptMsgClose(hDecodedMsg);
-            CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
-            return false;
-        }
-
-        CryptMsgClose(hDecodedMsg);
-    }
-
-    DWORD nSigLen = 0;
-
-    if (!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, nullptr, &nSigLen))
-    {
-        SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_CONTENT_PARAM) failed: " << WindowsErrorString(GetLastError()));
-        if (pTsContext)
-            CryptMemFree(pTsContext);
-        CryptMsgClose(hMsg);
-        CertFreeCertificateContext(pCertContext);
-        return false;
-    }
-
-    if (nSigLen*2 > MAX_SIGNATURE_CONTENT_LENGTH)
-    {
-        SAL_WARN("vcl.pdfwriter", "Signature requires more space (" << nSigLen*2 << ") than we reserved (" << MAX_SIGNATURE_CONTENT_LENGTH << ")");
-        if (pTsContext)
-            CryptMemFree(pTsContext);
-        CryptMsgClose(hMsg);
-        CertFreeCertificateContext(pCertContext);
-        return false;
-    }
-
-    SAL_INFO("vcl.pdfwriter", "Signature size is " << nSigLen << " bytes");
-    std::unique_ptr<BYTE[]> pSig(new BYTE[nSigLen]);
-
-    if (!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, pSig.get(), &nSigLen))
-    {
-        SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_CONTENT_PARAM) failed: " << WindowsErrorString(GetLastError()));
-        if (pTsContext)
-            CryptMemFree(pTsContext);
-        CryptMsgClose(hMsg);
-        CertFreeCertificateContext(pCertContext);
-        return false;
-    }
-
-#ifdef DBG_UTIL
-    {
-        FILE *out = fopen("PDFWRITER.signature.data", "wb");
-        fwrite(pSig.get(), nSigLen, 1, out);
-        fclose(out);
-    }
-#endif
-
-    // Release resources
-    if (pTsContext)
-        CryptMemFree(pTsContext);
-    CryptMsgClose(hMsg);
-    CertFreeCertificateContext(pCertContext);
-
-    for (unsigned int i = 0; i < nSigLen ; i++)
-        appendHex(pSig[i], rContext.m_rCMSHexBuffer);
-
-    return true;
-#endif
-}
-
 bool PDFWriterImpl::finalizeSignature()
 {
-
     if (!m_aContext.SignCertificate.is())
         return false;
 
@@ -7164,15 +5408,6 @@ bool PDFWriterImpl::finalizeSignature()
     }
 
     // 3- create the PKCS#7 object using NSS
-    css::uno::Sequence< sal_Int8 > derEncoded = m_aContext.SignCertificate->getEncoded();
-
-    if (!derEncoded.hasElements())
-        return false;
-
-    sal_Int8* n_derArray = derEncoded.getArray();
-    sal_Int32 n_derLength = derEncoded.getLength();
-
-#ifndef _WIN32
 
     // Prepare buffer and calculate PDF file digest
     CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, 0)) );
@@ -7181,51 +5416,6 @@ bool PDFWriterImpl::finalizeSignature()
     sal_uInt64 bytesRead1;
 
     //FIXME: Check if hash is calculated from the correct byterange
-    CHECK_RETURN( (osl::File::E_None == m_aFile.read(buffer1.get(), m_nSignatureContentOffset - 1 , bytesRead1)) );
-    if (bytesRead1 != (sal_uInt64)m_nSignatureContentOffset - 1)
-        SAL_WARN("vcl.pdfwriter", "First buffer read failed");
-
-    CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, m_nSignatureContentOffset + MAX_SIGNATURE_CONTENT_LENGTH + 1)) );
-    std::unique_ptr<char[]> buffer2(new char[nLastByteRangeNo + 1]);
-    sal_uInt64 bytesRead2;
-    CHECK_RETURN( (osl::File::E_None == m_aFile.read(buffer2.get(), nLastByteRangeNo, bytesRead2)) );
-    if (bytesRead2 != (sal_uInt64) nLastByteRangeNo)
-        SAL_WARN("vcl.pdfwriter", "Second buffer read failed");
-
-    OStringBuffer cms_hexbuffer;
-    PDFWriter::PDFSignContext aSignContext(cms_hexbuffer);
-    aSignContext.m_pDerEncoded = n_derArray;
-    aSignContext.m_nDerEncoded = n_derLength;
-    aSignContext.m_pByteRange1 = buffer1.get();
-    aSignContext.m_nByteRange1 = bytesRead1;
-    aSignContext.m_pByteRange2 = buffer2.get();
-    aSignContext.m_nByteRange2 = bytesRead2;
-    aSignContext.m_aSignTSA = m_aContext.SignTSA;
-    aSignContext.m_aSignPassword = m_aContext.SignPassword;
-    if (!PDFWriter::Sign(aSignContext))
-    {
-        SAL_WARN("vcl.pdfwriter", "PDFWriter::Sign() failed");
-        return false;
-    }
-
-    assert(cms_hexbuffer.getLength() <= MAX_SIGNATURE_CONTENT_LENGTH);
-
-    // Set file pointer to the m_nSignatureContentOffset, we're ready to overwrite PKCS7 object
-    nWritten = 0;
-    CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, m_nSignatureContentOffset)) );
-    m_aFile.write(cms_hexbuffer.getStr(), cms_hexbuffer.getLength(), nWritten);
-
-    CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, nOffset)) );
-    return true;
-
-#else
-
-    // Prepare buffer and calculate PDF file digest
-    CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, 0)) );
-
-    std::unique_ptr<char[]> buffer1(new char[m_nSignatureContentOffset - 1]);
-    sal_uInt64 bytesRead1;
-
     if (osl::File::E_None != m_aFile.read(buffer1.get(), m_nSignatureContentOffset - 1 , bytesRead1) ||
         bytesRead1 != (sal_uInt64)m_nSignatureContentOffset - 1)
     {
@@ -7233,7 +5423,7 @@ bool PDFWriterImpl::finalizeSignature()
         return false;
     }
 
-    std::unique_ptr<char[]> buffer2(new char[nLastByteRangeNo]);
+    std::unique_ptr<char[]> buffer2(new char[nLastByteRangeNo + 1]);
     sal_uInt64 bytesRead2;
 
     if (osl::File::E_None != m_aFile.setPos(osl_Pos_Absolut, m_nSignatureContentOffset + MAX_SIGNATURE_CONTENT_LENGTH + 1) ||
@@ -7244,42 +5434,30 @@ bool PDFWriterImpl::finalizeSignature()
         return false;
     }
 
-    OStringBuffer cms_hexbuffer;
-    PDFWriter::PDFSignContext aSignContext(cms_hexbuffer);
-    aSignContext.m_pDerEncoded = n_derArray;
-    aSignContext.m_nDerEncoded = n_derLength;
-    aSignContext.m_pByteRange1 = buffer1.get();
-    aSignContext.m_nByteRange1 = bytesRead1;
-    aSignContext.m_pByteRange2 = buffer2.get();
-    aSignContext.m_nByteRange2 = bytesRead2;
-    aSignContext.m_aSignTSA = m_aContext.SignTSA;
-    aSignContext.m_aSignPassword = m_aContext.SignPassword;
-    if (!PDFWriter::Sign(aSignContext))
+    OStringBuffer aCMSHexBuffer;
+    svl::crypto::Signing aSigning(m_aContext.SignCertificate);
+    aSigning.AddDataRange(buffer1.get(), bytesRead1);
+    aSigning.AddDataRange(buffer2.get(), bytesRead2);
+    aSigning.SetSignTSA(m_aContext.SignTSA);
+    aSigning.SetSignPassword(m_aContext.SignPassword);
+    if (!aSigning.Sign(aCMSHexBuffer))
     {
         SAL_WARN("vcl.pdfwriter", "PDFWriter::Sign() failed");
         return false;
     }
 
-    assert(cms_hexbuffer.getLength() <= MAX_SIGNATURE_CONTENT_LENGTH);
+    assert(aCMSHexBuffer.getLength() <= MAX_SIGNATURE_CONTENT_LENGTH);
 
     // Set file pointer to the m_nSignatureContentOffset, we're ready to overwrite PKCS7 object
     nWritten = 0;
     CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, m_nSignatureContentOffset)) );
-    m_aFile.write(cms_hexbuffer.getStr(), cms_hexbuffer.getLength(), nWritten);
+    m_aFile.write(aCMSHexBuffer.getStr(), aCMSHexBuffer.getLength(), nWritten);
 
     CHECK_RETURN( (osl::File::E_None == m_aFile.setPos(osl_Pos_Absolut, nOffset)) );
-
     return true;
-#endif
 }
 
-#else // !HAVE_FEATURE_NSS
-bool PDFWriter::Sign(PDFSignContext& /*rContext*/)
-{
-    // Not implemented.
-    return false;
-}
-#endif
+#endif //HAVE_FEATURE_NSS
 
 sal_Int32 PDFWriterImpl::emitInfoDict( )
 {


More information about the Libreoffice-commits mailing list