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.stahl@allotropia.de>
This commit is contained in:
Michael Stahl
2022-04-29 13:06:31 +02:00
parent c9e758e396
commit 5592ee094c
+26 -1
View File
@@ -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");