summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sal/log-areas.dox1
-rw-r--r--xmlsecurity/source/component/documentdigitalsignatures.cxx7
-rw-r--r--xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx6
-rw-r--r--xmlsecurity/source/gpg/SecurityEnvironment.cxx30
-rw-r--r--xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx157
5 files changed, 154 insertions, 47 deletions
diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox
index 4a8c692e061d..f414c0e2b423 100644
--- a/include/sal/log-areas.dox
+++ b/include/sal/log-areas.dox
@@ -528,6 +528,7 @@ certain functionality.
@li @c xmlsecurity.helper
@li @c xmlsecurity.pdfio - signing of existing PDF
@li @c xmlsecurity.xmlsec - xmlsec wrapper
+@li @c xmlsecurity.xmlsec.gpg - gpg xmlsec component
@section xmlscript
diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx
index 4dfa87edeeda..7d2068d8133b 100644
--- a/xmlsecurity/source/component/documentdigitalsignatures.cxx
+++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx
@@ -307,6 +307,7 @@ DocumentDigitalSignatures::ImplVerifySignatures(
rSignatureHelper.EndMission();
uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = aSignatureManager.getSecurityEnvironment();
+ uno::Reference<xml::crypto::XSecurityEnvironment> xGpgSecEnv = aSignatureManager.getGpgSecurityEnvironment();
SignatureInformations aSignInfos = rSignatureHelper.GetSignatureInformations();
int nInfos = aSignInfos.size();
@@ -359,7 +360,11 @@ DocumentDigitalSignatures::ImplVerifySignatures(
{
//We should always be able to get the certificates because it is contained in the document,
//unless the document is damaged so that signature xml file could not be parsed.
- rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID;
+ rSigInfo.CertificateStatus =
+ xGpgSecEnv->verifyCertificate(rSigInfo.Signer,
+ Sequence<Reference<css::security::XCertificate> >());
+ // well - except for gpg signatures ...
+ //rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID;
}
rSigInfo.SignatureIsValid = ( rInfo.nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED );
diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
index f691ab063157..9c7ff5f6163d 100644
--- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
+++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
@@ -500,6 +500,7 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox()
m_pSignaturesLB->Clear();
uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureManager.getSecurityEnvironment();
+ uno::Reference<xml::crypto::XSecurityEnvironment> xGpgSecEnv = maSignatureManager.getGpgSecurityEnvironment();
uno::Reference< css::security::XCertificate > xCert;
@@ -535,6 +536,8 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox()
//Todo: This probably could be removed, see above.
if (!xCert.is())
xCert = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xmlsecurity::numericStringToBigInteger( rInfo.ouX509SerialNumber ) );
+ if (!xCert.is())
+ xCert = xGpgSecEnv->getCertificate( rInfo.ouX509IssuerName, xmlsecurity::numericStringToBigInteger( rInfo.ouX509SerialNumber ) );
SAL_WARN_IF( !xCert.is(), "xmlsecurity.dialogs", "Certificate not found and can't be created!" );
@@ -550,7 +553,8 @@ void DigitalSignaturesDialog::ImplFillSignaturesBox()
{
//check the validity of the cert
try {
- sal_Int32 certResult = xSecEnv->verifyCertificate(xCert,
+ // TODO: check for both sec envs ...
+ sal_Int32 certResult = xGpgSecEnv->verifyCertificate(xCert,
Sequence<css::uno::Reference<css::security::XCertificate> >());
bCertValid = certResult == css::security::CertificateValidity::VALID;
diff --git a/xmlsecurity/source/gpg/SecurityEnvironment.cxx b/xmlsecurity/source/gpg/SecurityEnvironment.cxx
index 323e267af6b0..83e6170a98c1 100644
--- a/xmlsecurity/source/gpg/SecurityEnvironment.cxx
+++ b/xmlsecurity/source/gpg/SecurityEnvironment.cxx
@@ -94,8 +94,36 @@ Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getPersonalCertif
return xCertificateSequence;
}
-Reference< XCertificate > SecurityEnvironmentGpg::getCertificate( const OUString& /*issuerName*/, const Sequence< sal_Int8 >& /*serialNumber*/ )
+Reference< XCertificate > SecurityEnvironmentGpg::getCertificate( const OUString& issuerName, const Sequence< sal_Int8 >& /*serialNumber*/ )
{
+ GpgME::initializeLibrary();
+ GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
+ if (err)
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ GpgME::Context* ctx = GpgME::Context::createForProtocol(GpgME::OpenPGP);
+ if (ctx == nullptr)
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ CertificateImpl* xCert=nullptr;
+ std::list< CertificateImpl* > certsList;
+
+ ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
+ OString ostr = OUStringToOString( issuerName , RTL_TEXTENCODING_UTF8 );
+ err = ctx->startKeyListing(ostr.getStr(), true);
+ while (!err) {
+ GpgME::Key k = ctx->nextKey(err);
+ if (err)
+ break;
+ if (!k.isInvalid()) {
+ xCert = new CertificateImpl();
+ xCert->setCertificate(k);
+ ctx->endKeyListing();
+ return xCert;
+ }
+ }
+ ctx->endKeyListing();
+
return nullptr;
}
diff --git a/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx b/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx
index 673e50b9fa7d..eee8d5f83434 100644
--- a/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx
+++ b/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx
@@ -115,7 +115,10 @@ SAL_CALL XMLSignature_GpgImpl::generate(
// set intended operation to sign - several asserts inside libxmlsec
// wanting that for digest / transforms
- pDsigCtx->operation = xmlSecTransformOperationSign;
+ pDsigCtx->operation = xmlSecTransformOperationSign;
+
+ // we default to SHA512 for all digests - nss crypto does not have it...
+ //pDsigCtx->defDigestMethodId = xmlSecTransformSha512Id;
// Calculate digest for all references
xmlNodePtr cur = xmlSecGetNextElementNode(pNode->children);
@@ -233,11 +236,8 @@ SAL_CALL XMLSignature_GpgImpl::validate(
const Reference< XXMLSignatureTemplate >& aTemplate ,
const Reference< XXMLSecurityContext >& aSecurityCtx
) {
- xmlSecKeysMngrPtr pMngr = nullptr ;
xmlSecDSigCtxPtr pDsigCtx = nullptr ;
xmlNodePtr pNode = nullptr ;
- //sal_Bool valid ;
- (void)pMngr; (void)pDsigCtx; (void)pNode;
if( !aTemplate.is() )
throw RuntimeException() ;
@@ -274,72 +274,141 @@ SAL_CALL XMLSignature_GpgImpl::validate(
{
Reference< XSecurityEnvironment > aEnvironment = aSecurityCtx->getSecurityEnvironmentByIndex(i);
- //Get Keys Manager
- Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ;
#if 0
- SecurityEnvironment_NssImpl* pSecEnv =
- reinterpret_cast<SecurityEnvironment_NssImpl*>(
- sal::static_int_cast<sal_uIntPtr>(
- xSecTunnel->getSomething( SecurityEnvironment_NssImpl::getUnoTunnelId() )));
+ //Get Keys Manager
+ SecurityEnvironmentGpg* pSecEnv =
+ dynamic_cast<SecurityEnvironmentGpg*>(aEnvironment.get());
if( pSecEnv == nullptr )
throw RuntimeException() ;
+#endif
- pMngr = pSecEnv->createKeysManager();
- if( !pMngr ) {
- throw RuntimeException() ;
- }
+ // TODO pSecEnv is still from nss, roll our own impl there
+ // TODO figure out key from pSecEnv!
+ // unclear how/where that is transported in nss impl...
//Create Signature context
- pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ;
+ pDsigCtx = xmlSecDSigCtxCreate( nullptr ) ;
if( pDsigCtx == nullptr )
{
- SecurityEnvironment_NssImpl::destroyKeysManager( pMngr );
- //throw XMLSignatureException() ;
clearErrorRecorder();
return aTemplate;
}
- //Verify signature
- int rs = xmlSecDSigCtxVerify( pDsigCtx , pNode );
+ // set intended operation to verify - several asserts inside libxmlsec
+ // wanting that for digest / transforms
+ pDsigCtx->operation = xmlSecTransformOperationVerify;
- // Also verify manifest: this is empty for ODF, but contains everything (except signature metadata) for OOXML.
- xmlSecSize nReferenceCount = xmlSecPtrListGetSize(&pDsigCtx->manifestReferences);
- // Require that all manifest references are also good.
- xmlSecSize nReferenceGood = 0;
- for (xmlSecSize nReference = 0; nReference < nReferenceCount; ++nReference)
- {
- xmlSecDSigReferenceCtxPtr pReference = static_cast<xmlSecDSigReferenceCtxPtr>(xmlSecPtrListGetItem(&pDsigCtx->manifestReferences, nReference));
- if (pReference)
- {
- if (pReference->status == xmlSecDSigStatusSucceeded)
- ++nReferenceGood;
- }
- }
+ // reset status - to be set later
+ pDsigCtx->status = xmlSecDSigStatusUnknown;
+
+ // get me a digestible buffer from the SignatureInfo node!
+ // -------------------------------------------------------
+
+ // run the transformations - first child node is required to
+ // be SignatureInfo
+ xmlSecNodeSetPtr nodeset = nullptr;
+ xmlNodePtr cur = xmlSecGetNextElementNode(pNode->children);
+ // TODO assert that...
+ nodeset = xmlSecNodeSetGetChildren(pNode->doc, cur, 1, 0);
+ if(nodeset == nullptr)
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ // TODO assert we really have the SignatureInfo here?
+ if( xmlSecTransformCtxXmlExecute(&(pDsigCtx->transformCtx), nodeset) < 0 )
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ // Validate the template via gpgme
+ GpgME::initializeLibrary();
+ if( GpgME::checkEngine(GpgME::OpenPGP) )
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ GpgME::Context* ctx = GpgME::Context::createForProtocol(GpgME::OpenPGP);
+ if( ctx == nullptr )
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ // good, ctx is setup now, let's validate the lot
+ GpgME::Data data_text(
+ reinterpret_cast<char*>(xmlSecBufferGetData(pDsigCtx->transformCtx.result)),
+ xmlSecBufferGetSize(pDsigCtx->transformCtx.result), false);
+
+ SAL_INFO("xmlsecurity.xmlsec.gpg", "Validating SignatureInfo: " << xmlSecBufferGetData(pDsigCtx->transformCtx.result));
- if (rs == 0 && pDsigCtx->status == xmlSecDSigStatusSucceeded && nReferenceCount == nReferenceGood)
+ // walk xml tree to sign value node - go to children, first is
+ // SignedInfo, 2nd is signaturevalue
+ cur = xmlSecGetNextElementNode(pNode->children);
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ // TODO some assert would be good that cur is actually SignatureValue
+ xmlChar* pSignatureValue=xmlNodeGetContent(cur);
+ GpgME::Data data_signature(
+ reinterpret_cast<char*>(pSignatureValue),
+ xmlStrlen(pSignatureValue), false);
+
+ GpgME::VerificationResult verify_res=ctx->verifyDetachedSignature(
+ data_signature, data_text);
+
+ xmlFree(pSignatureValue);
+
+ // TODO: needs some more error handling, needs checking _all_ signatures
+ if( verify_res.isNull() ||
+ verify_res.numSignatures() == 0 ||
+ verify_res.signature(0).validity() < GpgME::Signature::Full )
{
- aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
- xmlSecDSigCtxDestroy( pDsigCtx ) ;
- SecurityEnvironment_NssImpl::destroyKeysManager( pMngr );
- break;
+ clearErrorRecorder();
+ return aTemplate;
}
- else
+
+ // now verify digest for all references
+ cur = xmlSecGetNextElementNode(pNode->children);
+ if( cur != nullptr )
+ cur = xmlSecGetNextElementNode(cur->children);
+ while( cur != nullptr )
{
- aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
+ // some of those children I suppose should be reference elements
+ if( xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs) )
+ {
+ xmlSecDSigReferenceCtxPtr pDsigRefCtx =
+ xmlSecDSigReferenceCtxCreate(pDsigCtx,
+ xmlSecDSigReferenceOriginSignedInfo);
+ if(pDsigRefCtx == nullptr)
+ throw RuntimeException();
+
+ // add this one to the list
+ if( xmlSecPtrListAdd(&(pDsigCtx->signedInfoReferences),
+ pDsigRefCtx) < 0 )
+ {
+ // TODO resource handling
+ xmlSecDSigReferenceCtxDestroy(pDsigRefCtx);
+ throw RuntimeException();
+ }
+
+ if( xmlSecDSigReferenceCtxProcessNode(pDsigRefCtx, cur) < 0 )
+ throw RuntimeException();
+
+ // final check - all good?
+ if(pDsigRefCtx->status != xmlSecDSigStatusSucceeded)
+ {
+ pDsigCtx->status = xmlSecDSigStatusInvalid;
+ return aTemplate; // TODO - harder error?
+ }
+ }
+
+ cur = xmlSecGetNextElementNode(cur->next);
}
+
+ // TODO - also verify manifest (only relevant for ooxml)?
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
+
+ // done
xmlSecDSigCtxDestroy( pDsigCtx ) ;
- SecurityEnvironment_NssImpl::destroyKeysManager( pMngr );
-#endif
}
-
//Unregistered the stream/URI binding
if( xUriBinding.is() )
xmlUnregisterStreamInputCallbacks() ;
- //return valid ;
clearErrorRecorder();
- return aTemplate;
+ return aTemplate ;
}
/* XServiceInfo */