svl/source/crypto/cryptosign.cxx |   27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

New commits:
commit 5592ee094ca9f09bfcc16537d931518d4e6b2231
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Thu Apr 28 16:31:51 2022 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Apr 29 13:06:31 2022 +0200

    svl: fix testSignDocument_PEM_PDF with "dbm:" NSS DB
    
    CentOS 7 system NSS defaults to legacy "dbm:" DB.
    
      test_desktop_lib.cxx:2943:Assertion
      Test name: DesktopLOKTest::testSignDocument_PEM_PDF
      assertion failed
      - Expression: bResult
    
    NSS_CMSSignerInfo_Sign() (called from NSS_CMSEncoder_Finish())
    internally calls PK11_FindKeyByAnyCert() and that fails likely for same
    reasons as documented in previous commit.
    
    The workaround here is a bit more involved, it turns out there's another
    path with NSSCMSSignerID_SubjectKeyID where the caller can pass in a
    SECKEYPrivateKey, let's try to do that as a fallback if a manual call to
    find the key fails.
    
    Change-Id: I298ee72f178220bcf644093917dba8143b092c92
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133577
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/svl/source/crypto/cryptosign.cxx b/svl/source/crypto/cryptosign.cxx
index ff8120ede34a..1e284506de01 100644
--- a/svl/source/crypto/cryptosign.cxx
+++ b/svl/source/crypto/cryptosign.cxx
@@ -33,6 +33,8 @@
 #if USE_CRYPTO_NSS
 // NSS headers for PDF signing
 #include <cert.h>
+#include <keyhi.h>
+#include <pk11pub.h>
 #include <hasht.h>
 #include <secerr.h>
 #include <sechash.h>
@@ -634,7 +636,30 @@ NSSCMSMessage *CreateCMSMessage(const PRTime* time,
         return nullptr;
     }
 
-    *cms_signer = NSS_CMSSignerInfo_Create(result, cert, SEC_OID_SHA256);
+    // workaround: with legacy "dbm:", NSS can't find the private key - try out
+    // if it works, and fallback if it doesn't.
+    if (SECKEYPrivateKey * pPrivateKey = PK11_FindKeyByAnyCert(cert, nullptr))
+    {
+        SECKEY_DestroyPrivateKey(pPrivateKey);
+        *cms_signer = NSS_CMSSignerInfo_Create(result, cert, SEC_OID_SHA256);
+    }
+    else
+    {
+        pPrivateKey = PK11_FindKeyByDERCert(cert->slot, cert, nullptr);
+        SECKEYPublicKey *const pPublicKey = CERT_ExtractPublicKey(cert);
+        if (pPublicKey && pPrivateKey)
+        {
+            *cms_signer = NSS_CMSSignerInfo_CreateWithSubjKeyID(result, 
&cert->subjectKeyID, pPublicKey, pPrivateKey, SEC_OID_SHA256);
+            SECKEY_DestroyPrivateKey(pPrivateKey);
+            SECKEY_DestroyPublicKey(pPublicKey);
+            if (*cms_signer)
+            {
+                // this is required in NSS_CMSSignerInfo_IncludeCerts()
+                // (and NSS_CMSSignerInfo_GetSigningCertificate() doesn't work)
+                (**cms_signer).cert = CERT_DupCertificate(cert);
+            }
+        }
+    }
     if (!*cms_signer)
     {
         SAL_WARN("svl.crypto", "NSS_CMSSignerInfo_Create failed");

Reply via email to