1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <pdfsignaturehelper.hxx>
14 #include <com/sun/star/io/XTruncate.hpp>
15 #include <com/sun/star/security/CertificateValidity.hpp>
16 #include <com/sun/star/uno/SecurityException.hpp>
17 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
18 #include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
20 #include <tools/stream.hxx>
21 #include <unotools/ucbstreamhelper.hxx>
22 #include <vcl/filter/pdfdocument.hxx>
24 #include <pdfio/pdfdocument.hxx>
25 #include <tools/diagnose_ex.h>
27 using namespace ::com::sun::star
;
29 PDFSignatureHelper::PDFSignatureHelper() = default;
31 bool PDFSignatureHelper::ReadAndVerifySignature(
32 const uno::Reference
<io::XInputStream
>& xInputStream
)
34 if (!xInputStream
.is())
36 SAL_WARN("xmlsecurity.helper", "input stream missing");
40 std::unique_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream(xInputStream
, true));
41 vcl::filter::PDFDocument aDocument
;
42 if (!aDocument
.Read(*pStream
))
44 SAL_WARN("xmlsecurity.helper", "failed to read the document");
48 std::vector
<vcl::filter::PDFObjectElement
*> aSignatures
= aDocument
.GetSignatureWidgets();
49 if (aSignatures
.empty())
52 m_aSignatureInfos
.clear();
54 for (size_t i
= 0; i
< aSignatures
.size(); ++i
)
56 SignatureInformation
aInfo(i
);
58 bool bLast
= i
== aSignatures
.size() - 1;
59 if (!xmlsecurity::pdfio::ValidateSignature(*pStream
, aSignatures
[i
], aInfo
, bLast
))
60 SAL_WARN("xmlsecurity.helper", "failed to determine digest match");
62 m_aSignatureInfos
.push_back(aInfo
);
68 SignatureInformations
const& PDFSignatureHelper::GetSignatureInformations() const
70 return m_aSignatureInfos
;
73 uno::Sequence
<security::DocumentSignatureInformation
>
74 PDFSignatureHelper::GetDocumentSignatureInformations(
75 const uno::Reference
<xml::crypto::XSecurityEnvironment
>& xSecEnv
) const
77 uno::Sequence
<security::DocumentSignatureInformation
> aRet(m_aSignatureInfos
.size());
79 for (size_t i
= 0; i
< m_aSignatureInfos
.size(); ++i
)
81 const SignatureInformation
& rInternal
= m_aSignatureInfos
[i
];
82 security::DocumentSignatureInformation
& rExternal
= aRet
[i
];
83 rExternal
.SignatureIsValid
84 = rInternal
.nStatus
== xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED
;
85 if (!rInternal
.ouX509Certificate
.isEmpty())
86 rExternal
.Signer
= xSecEnv
->createCertificateFromAscii(rInternal
.ouX509Certificate
);
87 rExternal
.PartialDocumentSignature
= rInternal
.bPartialDocumentSignature
;
89 // Verify certificate.
90 if (rExternal
.Signer
.is())
94 rExternal
.CertificateStatus
= xSecEnv
->verifyCertificate(rExternal
.Signer
, {});
96 catch (const uno::SecurityException
&)
98 DBG_UNHANDLED_EXCEPTION("xmlsecurity.helper", "failed to verify certificate");
99 rExternal
.CertificateStatus
= security::CertificateValidity::INVALID
;
103 rExternal
.CertificateStatus
= security::CertificateValidity::INVALID
;
109 sal_Int32
PDFSignatureHelper::GetNewSecurityId() const { return m_aSignatureInfos
.size(); }
111 void PDFSignatureHelper::SetX509Certificate(
112 const uno::Reference
<security::XCertificate
>& xCertificate
)
114 m_xCertificate
= xCertificate
;
117 void PDFSignatureHelper::SetDescription(const OUString
& rDescription
)
119 m_aDescription
= rDescription
;
122 bool PDFSignatureHelper::Sign(const uno::Reference
<io::XInputStream
>& xInputStream
, bool bAdES
)
124 std::unique_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream(xInputStream
, true));
125 vcl::filter::PDFDocument aDocument
;
126 if (!aDocument
.Read(*pStream
))
128 SAL_WARN("xmlsecurity.helper", "failed to read the document");
132 if (!aDocument
.Sign(m_xCertificate
, m_aDescription
, bAdES
))
134 SAL_WARN("xmlsecurity.helper", "failed to sign");
138 uno::Reference
<io::XStream
> xStream(xInputStream
, uno::UNO_QUERY
);
139 std::unique_ptr
<SvStream
> pOutStream(utl::UcbStreamHelper::CreateStream(xStream
, true));
140 if (!aDocument
.Write(*pOutStream
))
142 SAL_WARN("xmlsecurity.helper", "failed to write signed data");
149 bool PDFSignatureHelper::RemoveSignature(const uno::Reference
<io::XInputStream
>& xInputStream
,
150 sal_uInt16 nPosition
)
152 std::unique_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream(xInputStream
, true));
153 vcl::filter::PDFDocument aDocument
;
154 if (!aDocument
.Read(*pStream
))
156 SAL_WARN("xmlsecurity.helper", "failed to read the document");
160 if (!aDocument
.RemoveSignature(nPosition
))
162 SAL_WARN("xmlsecurity.helper", "failed to remove signature");
166 uno::Reference
<io::XStream
> xStream(xInputStream
, uno::UNO_QUERY
);
167 uno::Reference
<io::XTruncate
> xTruncate(xStream
, uno::UNO_QUERY
);
170 SAL_WARN("xmlsecurity.helper", "failed to truncate");
173 xTruncate
->truncate();
174 std::unique_ptr
<SvStream
> pOutStream(utl::UcbStreamHelper::CreateStream(xStream
, true));
175 if (!aDocument
.Write(*pOutStream
))
177 SAL_WARN("xmlsecurity.helper", "failed to write without signature");
184 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */