svl/source/crypto/cryptosign.cxx |   81 ++++++++++++++++-----------------------
 1 file changed, 34 insertions(+), 47 deletions(-)

New commits:
commit 637e3c46192dc6fb5ff1a289f626b2fac698aed6
Author:     Juraj Šarinay <ju...@sarinay.com>
AuthorDate: Mon Jan 20 00:32:46 2025 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Apr 30 13:05:46 2025 +0200

    tdf#147452 Do not compute the signature twice when adding a timestamp on 
Windows
    
    For non-deterministic signature schemes (e.g. ECDSA) we produced invalid
    timestamps. The signature timestamped differed from the one actually
    output.
    
    Change-Id: I6717ad4f6ab644244bf97fefdefbd407f207cb05
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180519
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/svl/source/crypto/cryptosign.cxx b/svl/source/crypto/cryptosign.cxx
index 11bda7de4e17..3f56377bf903 100644
--- a/svl/source/crypto/cryptosign.cxx
+++ b/svl/source/crypto/cryptosign.cxx
@@ -1454,8 +1454,10 @@ bool Signing::Sign(OStringBuffer& rCMSHexBuffer)
             return false;
         }
     }
+    CertFreeCertificateContext(pCertContext);
 
     PCRYPT_TIMESTAMP_CONTEXT pTsContext = nullptr;
+    DWORD dwEncodedMessageParamType = CMSG_CONTENT_PARAM;
 
     if( !m_aSignTSA.isEmpty() )
     {
@@ -1469,7 +1471,6 @@ bool Signing::Sign(OStringBuffer& rCMSHexBuffer)
         {
             SAL_WARN("svl.crypto", "CryptMsgOpenToDecode failed: " << 
comphelper::WindowsErrorString(GetLastError()));
             CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
             return false;
         }
 
@@ -1480,7 +1481,6 @@ bool Signing::Sign(OStringBuffer& rCMSHexBuffer)
             SAL_WARN("svl.crypto", "CryptMsgGetParam(CMSG_BARE_CONTENT_PARAM) 
failed: " << comphelper::WindowsErrorString(GetLastError()));
             CryptMsgClose(hDecodedMsg);
             CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
             return false;
         }
 
@@ -1493,16 +1493,15 @@ bool Signing::Sign(OStringBuffer& rCMSHexBuffer)
             SAL_WARN("svl.crypto", "CryptMsgGetParam(CMSG_BARE_CONTENT_PARAM) 
failed: " << comphelper::WindowsErrorString(GetLastError()));
             CryptMsgClose(hDecodedMsg);
             CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
             return false;
         }
 
+        CryptMsgClose(hMsg);
+
         if (!CryptMsgUpdate(hDecodedMsg, pTsSig.get(), nTsSigLen, TRUE))
         {
             SAL_WARN("svl.crypto", "CryptMsgUpdate failed: " << 
comphelper::WindowsErrorString(GetLastError()));
             CryptMsgClose(hDecodedMsg);
-            CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
             return false;
         }
 
@@ -1511,8 +1510,6 @@ bool Signing::Sign(OStringBuffer& rCMSHexBuffer)
         {
             SAL_WARN("svl.crypto", "CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) 
failed: " << comphelper::WindowsErrorString(GetLastError()));
             CryptMsgClose(hDecodedMsg);
-            CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
             return false;
         }
 
@@ -1522,8 +1519,6 @@ bool Signing::Sign(OStringBuffer& rCMSHexBuffer)
         {
             SAL_WARN("svl.crypto", "CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) 
failed: " << comphelper::WindowsErrorString(GetLastError()));
             CryptMsgClose(hDecodedMsg);
-            CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
             return false;
         }
 
@@ -1552,19 +1547,11 @@ bool Signing::Sign(OStringBuffer& rCMSHexBuffer)
         {
             SAL_WARN("svl.crypto", "CryptRetrieveTimeStamp failed: " << 
comphelper::WindowsErrorString(GetLastError()));
             CryptMsgClose(hDecodedMsg);
-            CryptMsgClose(hMsg);
-            CertFreeCertificateContext(pCertContext);
             return false;
         }
 
         SAL_INFO("svl.crypto", "Time stamp size is " << pTsContext->cbEncoded 
<< " bytes");
 
-        // 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;
@@ -1575,45 +1562,48 @@ bool Signing::Sign(OStringBuffer& rCMSHexBuffer)
         aTimestampAttribute.cValue = 1;
         aTimestampAttribute.rgValue = &aTimestampBlob;
 
-        aSignerInfo.cUnauthAttr = 1;
-        aSignerInfo.rgUnauthAttr = &aTimestampAttribute;
+        DWORD nEncodedTsAttributeLen = 0;
+        if (!CryptEncodeObject(PKCS_7_ASN_ENCODING, PKCS_ATTRIBUTE, 
&aTimestampAttribute, nullptr, &nEncodedTsAttributeLen))
+        {
+            SAL_WARN("svl.crypto", "CryptEncodeObject(PKCS_ATTRIBUTE) failed: 
" << comphelper::WindowsErrorString(GetLastError()));
+            CryptMsgClose(hDecodedMsg);
+            return false;
+        }
 
-        CryptMsgClose(hMsg);
+        std::unique_ptr<BYTE[]> pEncodedTsAttributeBuf(new 
BYTE[nEncodedTsAttributeLen]);
 
-        hMsg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
-                                    CMSG_DETACHED_FLAG,
-                                    CMSG_SIGNED,
-                                    &aSignedInfo,
-                                    nullptr,
-                                    nullptr);
+        CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA aAddTsAttrPara;
+        aAddTsAttrPara.dwSignerIndex = 0;
+        aAddTsAttrPara.cbSize = sizeof(aAddTsAttrPara);
 
-        for (size_t i = 0; i < m_dataBlocks.size(); ++i)
+        if (!CryptEncodeObject(PKCS_7_ASN_ENCODING, PKCS_ATTRIBUTE, 
&aTimestampAttribute, pEncodedTsAttributeBuf.get(), &nEncodedTsAttributeLen))
         {
-            const bool last = (i == m_dataBlocks.size() - 1);
-            if (!hMsg ||
-                !CryptMsgUpdate(hMsg, static_cast<const BYTE 
*>(m_dataBlocks[i].first), m_dataBlocks[i].second, last))
-            {
-                SAL_WARN("svl.crypto", "Re-creating the message failed: " << 
comphelper::WindowsErrorString(GetLastError()));
-                CryptMemFree(pTsContext);
-                CryptMsgClose(hDecodedMsg);
-                CryptMsgClose(hMsg);
-                CertFreeCertificateContext(pCertContext);
-                return false;
-            }
+            SAL_WARN("svl.crypto", "CryptEncodeObject(PKCS_ATTRIBUTE) failed: 
" << comphelper::WindowsErrorString(GetLastError()));
+            CryptMsgClose(hDecodedMsg);
+            return false;
         }
 
-        CryptMsgClose(hDecodedMsg);
+         aAddTsAttrPara.blob.cbData = nEncodedTsAttributeLen;
+         aAddTsAttrPara.blob.pbData = pEncodedTsAttributeBuf.get();
+
+        if (!CryptMsgControl(hDecodedMsg, 0, CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR, 
&aAddTsAttrPara))
+        {
+            SAL_WARN("svl.crypto", 
"CryptMsgControl(CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR) failed: " << 
comphelper::WindowsErrorString(GetLastError()));
+            CryptMsgClose(hDecodedMsg);
+            return false;
+        }
+        hMsg = hDecodedMsg;
+        dwEncodedMessageParamType = CMSG_ENCODED_MESSAGE;
     }
 
     DWORD nSigLen = 0;
 
-    if (!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, nullptr, &nSigLen))
+    if (!CryptMsgGetParam(hMsg, dwEncodedMessageParamType, 0, nullptr, 
&nSigLen))
     {
-        SAL_WARN("svl.crypto", "CryptMsgGetParam(CMSG_CONTENT_PARAM) failed: " 
<< comphelper::WindowsErrorString(GetLastError()));
+        SAL_WARN("svl.crypto", "Reading the encoded message via 
CryptMsgGetParam() failed: " << comphelper::WindowsErrorString(GetLastError()));
         if (pTsContext)
             CryptMemFree(pTsContext);
         CryptMsgClose(hMsg);
-        CertFreeCertificateContext(pCertContext);
         return false;
     }
 
@@ -1623,20 +1613,18 @@ bool Signing::Sign(OStringBuffer& rCMSHexBuffer)
         if (pTsContext)
             CryptMemFree(pTsContext);
         CryptMsgClose(hMsg);
-        CertFreeCertificateContext(pCertContext);
         return false;
     }
 
     SAL_INFO("svl.crypto", "Signature size is " << nSigLen << " bytes");
     std::unique_ptr<BYTE[]> pSig(new BYTE[nSigLen]);
 
-    if (!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, pSig.get(), &nSigLen))
+    if (!CryptMsgGetParam(hMsg, dwEncodedMessageParamType, 0, pSig.get(), 
&nSigLen))
     {
-        SAL_WARN("svl.crypto", "CryptMsgGetParam(CMSG_CONTENT_PARAM) failed: " 
<< comphelper::WindowsErrorString(GetLastError()));
+        SAL_WARN("svl.crypto", "Reading the encoded message via 
CryptMsgGetParam() failed: " << comphelper::WindowsErrorString(GetLastError()));
         if (pTsContext)
             CryptMemFree(pTsContext);
         CryptMsgClose(hMsg);
-        CertFreeCertificateContext(pCertContext);
         return false;
     }
 
@@ -1644,7 +1632,6 @@ bool Signing::Sign(OStringBuffer& rCMSHexBuffer)
     if (pTsContext)
         CryptMemFree(pTsContext);
     CryptMsgClose(hMsg);
-    CertFreeCertificateContext(pCertContext);
 
     for (unsigned int i = 0; i < nSigLen ; i++)
         appendHex(pSig[i], rCMSHexBuffer);

Reply via email to