From 4f17445c12dc26c4881c4e486215b58d26515f8d Mon Sep 17 00:00:00 2001 From: Ashod Nakashian Date: Sun, 9 Jul 2017 09:42:01 -0400 Subject: svl: move byte-array verification from vcl Also use comphelper::Base64 and DateTime::CreateFromUnixTime to avoid depending on sax. Change-Id: If1853f8d9481c9caa0625a111707531bbc495f75 Reviewed-on: https://gerrit.libreoffice.org/39993 Tested-by: Jenkins Reviewed-by: Ashod Nakashian --- xmlsecurity/inc/certificatechooser.hxx | 2 +- xmlsecurity/inc/documentsignaturehelper.hxx | 2 +- xmlsecurity/inc/documentsignaturemanager.hxx | 2 +- xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx | 1 - xmlsecurity/inc/pdfsignaturehelper.hxx | 2 +- xmlsecurity/inc/sigstruct.hxx | 131 ----- xmlsecurity/inc/xmlsignaturehelper.hxx | 2 +- xmlsecurity/inc/xsecctl.hxx | 2 +- xmlsecurity/source/helper/ooxmlsecexporter.hxx | 2 +- xmlsecurity/source/pdfio/pdfdocument.cxx | 641 +----------------------- xmlsecurity/workben/pdfverify.cxx | 2 +- 11 files changed, 12 insertions(+), 777 deletions(-) delete mode 100644 xmlsecurity/inc/sigstruct.hxx (limited to 'xmlsecurity') diff --git a/xmlsecurity/inc/certificatechooser.hxx b/xmlsecurity/inc/certificatechooser.hxx index 264b740dd448..009d20e4ea2f 100644 --- a/xmlsecurity/inc/certificatechooser.hxx +++ b/xmlsecurity/inc/certificatechooser.hxx @@ -28,7 +28,7 @@ #include #include #include -#include +#include namespace com { diff --git a/xmlsecurity/inc/documentsignaturehelper.hxx b/xmlsecurity/inc/documentsignaturehelper.hxx index a8f3cb1f5d40..3997ae47260d 100644 --- a/xmlsecurity/inc/documentsignaturehelper.hxx +++ b/xmlsecurity/inc/documentsignaturehelper.hxx @@ -23,7 +23,7 @@ #include #include #include -#include "sigstruct.hxx" +#include #include "xmlsecurity/xmlsecuritydllapi.h" #include diff --git a/xmlsecurity/inc/documentsignaturemanager.hxx b/xmlsecurity/inc/documentsignaturemanager.hxx index f354ad8c8cbb..0ea708c5d241 100644 --- a/xmlsecurity/inc/documentsignaturemanager.hxx +++ b/xmlsecurity/inc/documentsignaturemanager.hxx @@ -24,7 +24,7 @@ #include -#include +#include #include #include #include diff --git a/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx b/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx index cfb26d8593ae..07008a0b5181 100644 --- a/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx +++ b/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx @@ -302,6 +302,5 @@ #include #include #include -#include /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pdfsignaturehelper.hxx b/xmlsecurity/inc/pdfsignaturehelper.hxx index 74b89fe44e02..7da417c46e4f 100644 --- a/xmlsecurity/inc/pdfsignaturehelper.hxx +++ b/xmlsecurity/inc/pdfsignaturehelper.hxx @@ -19,7 +19,7 @@ #include #include -#include +#include /// Handles signatures of a PDF file. class XMLSECURITY_DLLPUBLIC PDFSignatureHelper diff --git a/xmlsecurity/inc/sigstruct.hxx b/xmlsecurity/inc/sigstruct.hxx deleted file mode 100644 index ff6ee5e5d3a5..000000000000 --- a/xmlsecurity/inc/sigstruct.hxx +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_XMLSECURITY_INC_SIGSTRUCT_HXX -#define INCLUDED_XMLSECURITY_INC_SIGSTRUCT_HXX - -#include -#include -#include -#include -#include - -#include -#include - -/* - * type of reference - */ -enum class SignatureReferenceType -{ - SAMEDOCUMENT = 1, - BINARYSTREAM = 2, - XMLSTREAM = 3 -}; - -struct SignatureReferenceInformation -{ - SignatureReferenceType nType; - OUString ouURI; - // For ODF: XAdES digests (SHA256) or the old SHA1, from css::xml::crypto::DigestID - sal_Int32 nDigestID; - OUString ouDigestValue; - - SignatureReferenceInformation() : - nType(SignatureReferenceType::SAMEDOCUMENT), - ouURI(""), - nDigestID(css::xml::crypto::DigestID::SHA1), - ouDigestValue("") - { - } - - SignatureReferenceInformation( SignatureReferenceType type, sal_Int32 digestID, const OUString& uri ) : - SignatureReferenceInformation() - { - nType = type; - nDigestID = digestID; - ouURI = uri; - } -}; - -typedef ::std::vector< SignatureReferenceInformation > SignatureReferenceInformations; - -struct SignatureInformation -{ - sal_Int32 nSecurityId; - css::xml::crypto::SecurityOperationStatus nStatus; - SignatureReferenceInformations vSignatureReferenceInfors; - OUString ouX509IssuerName; - OUString ouX509SerialNumber; - OUString ouX509Certificate; - - OUString ouGpgKeyID; - OUString ouGpgCertificate; - OUString ouGpgOwner; - - OUString ouSignatureValue; - css::util::DateTime stDateTime; - - // XAdES EncapsulatedX509Certificate values - std::set maEncapsulatedX509Certificates; - - //We also keep the date and time as string. This is done when this - //structure is created as a result of a XML signature being read. - //When then a signature is added or another removed, then the original - //XML signatures are written again (unless they have been removed). - //If the date time string is converted into the DateTime structure - //then information can be lost because it only holds a fractional - //of a second with a accuracy of one hundredth of second. - //If the string contains - //milli seconds (because the document was created by an application other than OOo) - //and the converted time is written back, then the string looks different - //and the signature is broken. - OUString ouDateTime; - OUString ouSignatureId; - OUString ouPropertyId; - /// Characters of the element inside the signature. - OUString ouDescription; - /// The Id attribute of the element that contains the . - OUString ouDescriptionPropertyId; - /// OOXML certificate SHA-256 digest, empty for ODF except when doing XAdES signature. - OUString ouCertDigest; - /// A full OOXML signature for unchanged roundtrip, empty for ODF. - css::uno::Sequence aSignatureBytes; - /// For PDF: digest format, from css::xml::crypto::DigestID - sal_Int32 nDigestID; - /// For PDF: has id-aa-signingCertificateV2 as a signed attribute. - bool bHasSigningCertificate; - /// For PDF: the byte range doesn't cover the whole document. - bool bPartialDocumentSignature; - - SignatureInformation( sal_Int32 nId ) - { - nSecurityId = nId; - nStatus = css::xml::crypto::SecurityOperationStatus_UNKNOWN; - nDigestID = 0; - bHasSigningCertificate = false; - bPartialDocumentSignature = false; - } -}; - -typedef ::std::vector< SignatureInformation > SignatureInformations; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsignaturehelper.hxx b/xmlsecurity/inc/xmlsignaturehelper.hxx index 209c93c15a09..d527942f50f2 100644 --- a/xmlsecurity/inc/xmlsignaturehelper.hxx +++ b/xmlsecurity/inc/xmlsignaturehelper.hxx @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include diff --git a/xmlsecurity/inc/xsecctl.hxx b/xmlsecurity/inc/xsecctl.hxx index 9ddc22affbae..27cb60e54dc0 100644 --- a/xmlsecurity/inc/xsecctl.hxx +++ b/xmlsecurity/inc/xsecctl.hxx @@ -20,7 +20,7 @@ #ifndef INCLUDED_XMLSECURITY_SOURCE_HELPER_XSECCTL_HXX #define INCLUDED_XMLSECURITY_SOURCE_HELPER_XSECCTL_HXX -#include +#include #include #include diff --git a/xmlsecurity/source/helper/ooxmlsecexporter.hxx b/xmlsecurity/source/helper/ooxmlsecexporter.hxx index 1a96430bba9a..12c7c197047c 100644 --- a/xmlsecurity/source/helper/ooxmlsecexporter.hxx +++ b/xmlsecurity/source/helper/ooxmlsecexporter.hxx @@ -15,7 +15,7 @@ #include #include #include -#include +#include /// Writes a single OOXML digital signature. class OOXMLSecExporter diff --git a/xmlsecurity/source/pdfio/pdfdocument.cxx b/xmlsecurity/source/pdfio/pdfdocument.cxx index 6925b41a1960..d0d56f4bd409 100644 --- a/xmlsecurity/source/pdfio/pdfdocument.cxx +++ b/xmlsecurity/source/pdfio/pdfdocument.cxx @@ -32,7 +32,8 @@ #include #include -#include +#include +#include #ifdef XMLSEC_CRYPTO_NSS #include @@ -56,232 +57,6 @@ namespace xmlsecurity namespace pdfio { -namespace -{ -#ifdef XMLSEC_CRYPTO_NSS -/// Similar to NSS_CMSAttributeArray_FindAttrByOidTag(), but works directly with a SECOidData. -NSSCMSAttribute* CMSAttributeArray_FindAttrByOidData(NSSCMSAttribute** attrs, SECOidData* oid, PRBool only) -{ - NSSCMSAttribute* attr1, *attr2; - - if (attrs == nullptr) - return nullptr; - - if (oid == nullptr) - return nullptr; - - while ((attr1 = *attrs++) != nullptr) - { - if (attr1->type.len == oid->oid.len && PORT_Memcmp(attr1->type.data, - oid->oid.data, - oid->oid.len) == 0) - break; - } - - if (attr1 == nullptr) - return nullptr; - - if (!only) - return attr1; - - while ((attr2 = *attrs++) != nullptr) - { - if (attr2->type.len == oid->oid.len && PORT_Memcmp(attr2->type.data, - oid->oid.data, - oid->oid.len) == 0) - break; - } - - if (attr2 != nullptr) - return nullptr; - - return attr1; -} - -/// Same as SEC_StringToOID(), which is private to us. -SECStatus StringToOID(SECItem* to, const char* from, PRUint32 len) -{ - PRUint32 decimal_numbers = 0; - PRUint32 result_bytes = 0; - SECStatus rv; - PRUint8 result[1024]; - - static const PRUint32 max_decimal = (0xffffffff / 10); - static const char OIDstring[] = {"OID."}; - - if (!from || !to) - { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - if (!len) - { - len = PL_strlen(from); - } - if (len >= 4 && !PL_strncasecmp(from, OIDstring, 4)) - { - from += 4; /* skip leading "OID." if present */ - len -= 4; - } - if (!len) - { -bad_data: - PORT_SetError(SEC_ERROR_BAD_DATA); - return SECFailure; - } - do - { - PRUint32 decimal = 0; - while (len > 0 && rtl::isAsciiDigit(static_cast(*from))) - { - PRUint32 addend = (*from++ - '0'); - --len; - if (decimal > max_decimal) /* overflow */ - goto bad_data; - decimal = (decimal * 10) + addend; - if (decimal < addend) /* overflow */ - goto bad_data; - } - if (len != 0 && *from != '.') - { - goto bad_data; - } - if (decimal_numbers == 0) - { - if (decimal > 2) - goto bad_data; - result[0] = decimal * 40; - result_bytes = 1; - } - else if (decimal_numbers == 1) - { - if (decimal > 40) - goto bad_data; - result[0] += decimal; - } - else - { - /* encode the decimal number, */ - PRUint8* rp; - PRUint32 num_bytes = 0; - PRUint32 tmp = decimal; - while (tmp) - { - num_bytes++; - tmp >>= 7; - } - if (!num_bytes) - ++num_bytes; /* use one byte for a zero value */ - if (static_cast(num_bytes) + result_bytes > sizeof result) - goto bad_data; - tmp = num_bytes; - rp = result + result_bytes - 1; - rp[tmp] = (PRUint8)(decimal & 0x7f); - decimal >>= 7; - while (--tmp > 0) - { - rp[tmp] = (PRUint8)(decimal | 0x80); - decimal >>= 7; - } - result_bytes += num_bytes; - } - ++decimal_numbers; - if (len > 0) /* skip trailing '.' */ - { - ++from; - --len; - } - } - while (len > 0); - /* now result contains result_bytes of data */ - if (to->data && to->len >= result_bytes) - { - PORT_Memcpy(to->data, result, to->len = result_bytes); - rv = SECSuccess; - } - else - { - SECItem result_item = {siBuffer, nullptr, 0 }; - result_item.data = result; - result_item.len = result_bytes; - rv = SECITEM_CopyItem(nullptr, to, &result_item); - } - return rv; -} -#elif defined XMLSEC_CRYPTO_MSCRYPTO -/// Verifies a non-detached signature using CryptoAPI. -bool VerifyNonDetachedSignature(SvStream& rStream, std::vector>& rByteRanges, std::vector& rExpectedHash) -{ - HCRYPTPROV hProv = 0; - if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) - { - SAL_WARN("xmlsecurity.pdfio", "CryptAcquireContext() failed"); - return false; - } - - HCRYPTHASH hHash = 0; - if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)) - { - SAL_WARN("xmlsecurity.pdfio", "CryptCreateHash() failed"); - return false; - } - - for (const auto& rByteRange : rByteRanges) - { - rStream.Seek(rByteRange.first); - const int nChunkLen = 4096; - std::vector aBuffer(nChunkLen); - for (size_t nByte = 0; nByte < rByteRange.second;) - { - size_t nRemainingSize = rByteRange.second - nByte; - if (nRemainingSize < nChunkLen) - { - rStream.ReadBytes(aBuffer.data(), nRemainingSize); - if (!CryptHashData(hHash, aBuffer.data(), nRemainingSize, 0)) - { - SAL_WARN("xmlsecurity.pdfio", "CryptHashData() failed"); - return false; - } - nByte = rByteRange.second; - } - else - { - rStream.ReadBytes(aBuffer.data(), nChunkLen); - if (!CryptHashData(hHash, aBuffer.data(), nChunkLen, 0)) - { - SAL_WARN("xmlsecurity.pdfio", "CryptHashData() failed"); - return false; - } - nByte += nChunkLen; - } - } - } - - DWORD nActualHash = 0; - if (!CryptGetHashParam(hHash, HP_HASHVAL, nullptr, &nActualHash, 0)) - { - SAL_WARN("xmlsecurity.pdfio", "CryptGetHashParam() failed to provide the hash length"); - return false; - } - - std::vector aActualHash(nActualHash); - if (!CryptGetHashParam(hHash, HP_HASHVAL, aActualHash.data(), &nActualHash, 0)) - { - SAL_WARN("xmlsecurity.pdfio", "CryptGetHashParam() failed to provide the hash"); - return false; - } - - CryptDestroyHash(hHash); - CryptReleaseContext(hProv, 0); - - if (!std::memcmp(aActualHash.data(), rExpectedHash.data(), aActualHash.size()) && aActualHash.size() == rExpectedHash.size()) - return true; - - return false; -} -#endif -} - bool ValidateSignature(SvStream& rStream, vcl::filter::PDFObjectElement* pSignature, SignatureInformation& rInformation, bool bLast) { vcl::filter::PDFObjectElement* pValue = pSignature->LookupObject("V"); @@ -306,7 +81,7 @@ bool ValidateSignature(SvStream& rStream, vcl::filter::PDFObjectElement* pSignat } auto pSubFilter = dynamic_cast(pValue->Lookup("SubFilter")); - bool bNonDetached = pSubFilter && pSubFilter->GetValue() == "adbe.pkcs7.sha1"; + const bool bNonDetached = pSubFilter && pSubFilter->GetValue() == "adbe.pkcs7.sha1"; if (!pSubFilter || (pSubFilter->GetValue() != "adbe.pkcs7.detached" && !bNonDetached && pSubFilter->GetValue() != "ETSI.CAdES.detached")) { if (!pSubFilter) @@ -414,415 +189,7 @@ bool ValidateSignature(SvStream& rStream, vcl::filter::PDFObjectElement* pSignat return false; } -#ifdef XMLSEC_CRYPTO_NSS - // Validate the signature. No need to call NSS_Init() here, assume that the - // caller did that already. - - SECItem aSignatureItem; - aSignatureItem.data = aSignature.data(); - aSignatureItem.len = aSignature.size(); - NSSCMSMessage* pCMSMessage = NSS_CMSMessage_CreateFromDER(&aSignatureItem, - /*cb=*/nullptr, - /*cb_arg=*/nullptr, - /*pwfn=*/nullptr, - /*pwfn_arg=*/nullptr, - /*decrypt_key_cb=*/nullptr, - /*decrypt_key_cb_arg=*/nullptr); - if (!NSS_CMSMessage_IsSigned(pCMSMessage)) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: message is not signed"); - return false; - } - - NSSCMSContentInfo* pCMSContentInfo = NSS_CMSMessage_ContentLevel(pCMSMessage, 0); - if (!pCMSContentInfo) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: NSS_CMSMessage_ContentLevel() failed"); - return false; - } - - auto pCMSSignedData = static_cast(NSS_CMSContentInfo_GetContent(pCMSContentInfo)); - if (!pCMSSignedData) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: NSS_CMSContentInfo_GetContent() failed"); - return false; - } - - // Import certificates from the signed data temporarily, so it'll be - // possible to verify the signature, even if we didn't have the certificate - // previously. - std::vector aDocumentCertificates; - for (size_t i = 0; pCMSSignedData->rawCerts[i]; ++i) - aDocumentCertificates.push_back(CERT_NewTempCertificate(CERT_GetDefaultCertDB(), pCMSSignedData->rawCerts[i], nullptr, 0, 0)); - - NSSCMSSignerInfo* pCMSSignerInfo = NSS_CMSSignedData_GetSignerInfo(pCMSSignedData, 0); - if (!pCMSSignerInfo) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: NSS_CMSSignedData_GetSignerInfo() failed"); - return false; - } - - SECItem aAlgorithm = NSS_CMSSignedData_GetDigestAlgs(pCMSSignedData)[0]->algorithm; - SECOidTag eOidTag = SECOID_FindOIDTag(&aAlgorithm); - - // Map a sign algorithm to a digest algorithm. - // See NSS_CMSUtil_MapSignAlgs(), which is private to us. - switch (eOidTag) - { - case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: - eOidTag = SEC_OID_SHA1; - break; - case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: - eOidTag = SEC_OID_SHA256; - break; - case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: - eOidTag = SEC_OID_SHA512; - break; - default: - break; - } - - HASH_HashType eHashType = HASH_GetHashTypeByOidTag(eOidTag); - HASHContext* pHASHContext = HASH_Create(eHashType); - if (!pHASHContext) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: HASH_Create() failed"); - return false; - } - - // We have a hash, update it with the byte ranges. - for (const auto& rByteRange : aByteRanges) - { - rStream.Seek(rByteRange.first); - - // And now hash this byte range. - const int nChunkLen = 4096; - std::vector aBuffer(nChunkLen); - for (size_t nByte = 0; nByte < rByteRange.second;) - { - size_t nRemainingSize = rByteRange.second - nByte; - if (nRemainingSize < nChunkLen) - { - rStream.ReadBytes(aBuffer.data(), nRemainingSize); - HASH_Update(pHASHContext, aBuffer.data(), nRemainingSize); - nByte = rByteRange.second; - } - else - { - rStream.ReadBytes(aBuffer.data(), nChunkLen); - HASH_Update(pHASHContext, aBuffer.data(), nChunkLen); - nByte += nChunkLen; - } - } - } - - // Find out what is the expected length of the hash. - unsigned int nMaxResultLen = 0; - switch (eOidTag) - { - case SEC_OID_SHA1: - nMaxResultLen = msfilter::SHA1_HASH_LENGTH; - rInformation.nDigestID = xml::crypto::DigestID::SHA1; - break; - case SEC_OID_SHA256: - nMaxResultLen = msfilter::SHA256_HASH_LENGTH; - rInformation.nDigestID = xml::crypto::DigestID::SHA256; - break; - case SEC_OID_SHA512: - nMaxResultLen = msfilter::SHA512_HASH_LENGTH; - break; - default: - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: unrecognized algorithm"); - return false; - } - - auto pActualResultBuffer = static_cast(PORT_Alloc(nMaxResultLen)); - unsigned int nActualResultLen; - HASH_End(pHASHContext, pActualResultBuffer, &nActualResultLen, nMaxResultLen); - - CERTCertificate* pCertificate = NSS_CMSSignerInfo_GetSigningCertificate(pCMSSignerInfo, CERT_GetDefaultCertDB()); - if (!pCertificate) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: NSS_CMSSignerInfo_GetSigningCertificate() failed"); - return false; - } - else - { - uno::Sequence aDerCert(pCertificate->derCert.len); - for (size_t i = 0; i < pCertificate->derCert.len; ++i) - aDerCert[i] = pCertificate->derCert.data[i]; - OUStringBuffer aBuffer; - sax::Converter::encodeBase64(aBuffer, aDerCert); - rInformation.ouX509Certificate = aBuffer.makeStringAndClear(); - } - - PRTime nSigningTime; - // This may fail, in which case the date should be taken from the dictionary's "M" key. - if (NSS_CMSSignerInfo_GetSigningTime(pCMSSignerInfo, &nSigningTime) == SECSuccess) - { - // First convert the UNIX timestamp to an ISO8601 string. - OUStringBuffer aBuffer; - uno::Reference xComponentContext = comphelper::getProcessComponentContext(); - CalendarWrapper aCalendarWrapper(xComponentContext); - // nSigningTime is in microseconds. - SvXMLUnitConverter::convertDateTime(aBuffer, static_cast(nSigningTime) / 1000000 / tools::Time::secondPerDay, aCalendarWrapper.getEpochStart().GetUNODate()); - - // Then convert this string to a local UNO DateTime. - util::DateTime aUNODateTime; - try - { - utl::ISO8601parseDateTime(aBuffer.toString(), aUNODateTime); - } - catch (const std::length_error&) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: failed to parse signature date string"); - return false; - } - DateTime aDateTime(aUNODateTime); - aDateTime.ConvertToLocalTime(); - rInformation.stDateTime = aDateTime.GetUNODateTime(); - } - - // Check if we have a signing certificate attribute. - SECOidData aOidData; - aOidData.oid.data = nullptr; - /* - * id-aa-signingCertificateV2 OBJECT IDENTIFIER ::= - * { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9) - * smime(16) id-aa(2) 47 } - */ - if (StringToOID(&aOidData.oid, "1.2.840.113549.1.9.16.2.47", 0) != SECSuccess) - { - SAL_WARN("xmlsecurity.pdfio", "StringToOID() failed"); - return false; - } - aOidData.offset = SEC_OID_UNKNOWN; - aOidData.desc = "id-aa-signingCertificateV2"; - aOidData.mechanism = CKM_SHA_1; - aOidData.supportedExtension = UNSUPPORTED_CERT_EXTENSION; - NSSCMSAttribute* pAttribute = CMSAttributeArray_FindAttrByOidData(pCMSSignerInfo->authAttr, &aOidData, PR_TRUE); - if (pAttribute) - rInformation.bHasSigningCertificate = true; - - SECItem* pContentInfoContentData = pCMSSignedData->contentInfo.content.data; - if (bNonDetached && pContentInfoContentData && pContentInfoContentData->data) - { - // Not a detached signature. - if (!std::memcmp(pActualResultBuffer, pContentInfoContentData->data, nMaxResultLen) && nActualResultLen == pContentInfoContentData->len) - rInformation.nStatus = xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; - } - else - { - // Detached, the usual case. - SECItem aActualResultItem; - aActualResultItem.data = pActualResultBuffer; - aActualResultItem.len = nActualResultLen; - if (NSS_CMSSignerInfo_Verify(pCMSSignerInfo, &aActualResultItem, nullptr) == SECSuccess) - rInformation.nStatus = xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; - } - - // Everything went fine - PORT_Free(pActualResultBuffer); - HASH_Destroy(pHASHContext); - NSS_CMSSignerInfo_Destroy(pCMSSignerInfo); - for (auto pDocumentCertificate : aDocumentCertificates) - CERT_DestroyCertificate(pDocumentCertificate); - - return true; -#elif defined XMLSEC_CRYPTO_MSCRYPTO - // Open a message for decoding. - HCRYPTMSG hMsg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, - CMSG_DETACHED_FLAG, - 0, - NULL, - nullptr, - nullptr); - if (!hMsg) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: CryptMsgOpenToDecode() failed"); - return false; - } - - // Update the message with the encoded header blob. - if (!CryptMsgUpdate(hMsg, aSignature.data(), aSignature.size(), TRUE)) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature, CryptMsgUpdate() for the header failed: " << WindowsErrorString(GetLastError())); - return false; - } - - // Update the message with the content blob. - for (const auto& rByteRange : aByteRanges) - { - rStream.Seek(rByteRange.first); - - const int nChunkLen = 4096; - std::vector aBuffer(nChunkLen); - for (size_t nByte = 0; nByte < rByteRange.second;) - { - size_t nRemainingSize = rByteRange.second - nByte; - if (nRemainingSize < nChunkLen) - { - rStream.ReadBytes(aBuffer.data(), nRemainingSize); - if (!CryptMsgUpdate(hMsg, aBuffer.data(), nRemainingSize, FALSE)) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature, CryptMsgUpdate() for the content failed: " << WindowsErrorString(GetLastError())); - return false; - } - nByte = rByteRange.second; - } - else - { - rStream.ReadBytes(aBuffer.data(), nChunkLen); - if (!CryptMsgUpdate(hMsg, aBuffer.data(), nChunkLen, FALSE)) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature, CryptMsgUpdate() for the content failed: " << WindowsErrorString(GetLastError())); - return false; - } - nByte += nChunkLen; - } - } - } - if (!CryptMsgUpdate(hMsg, nullptr, 0, TRUE)) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature, CryptMsgUpdate() for the last content failed: " << WindowsErrorString(GetLastError())); - return false; - } - - // Get the CRYPT_ALGORITHM_IDENTIFIER from the message. - DWORD nDigestID = 0; - if (!CryptMsgGetParam(hMsg, CMSG_SIGNER_HASH_ALGORITHM_PARAM, 0, nullptr, &nDigestID)) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: CryptMsgGetParam() failed: " << WindowsErrorString(GetLastError())); - return false; - } - std::unique_ptr pDigestBytes(new BYTE[nDigestID]); - if (!CryptMsgGetParam(hMsg, CMSG_SIGNER_HASH_ALGORITHM_PARAM, 0, pDigestBytes.get(), &nDigestID)) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: CryptMsgGetParam() failed: " << WindowsErrorString(GetLastError())); - return false; - } - auto pDigestID = reinterpret_cast(pDigestBytes.get()); - if (OString(szOID_NIST_sha256) == pDigestID->pszObjId) - rInformation.nDigestID = xml::crypto::DigestID::SHA256; - else if (OString(szOID_RSA_SHA1RSA) == pDigestID->pszObjId || OString(szOID_OIWSEC_sha1) == pDigestID->pszObjId) - rInformation.nDigestID = xml::crypto::DigestID::SHA1; - else - // Don't error out here, we can still verify the message digest correctly, just the digest ID won't be set. - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: unhandled algorithm identifier '"<pszObjId<<"'"); - - // Get the signer CERT_INFO from the message. - DWORD nSignerCertInfo = 0; - if (!CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_INFO_PARAM, 0, nullptr, &nSignerCertInfo)) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: CryptMsgGetParam() failed"); - return false; - } - std::unique_ptr pSignerCertInfoBuf(new BYTE[nSignerCertInfo]); - if (!CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_INFO_PARAM, 0, pSignerCertInfoBuf.get(), &nSignerCertInfo)) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: CryptMsgGetParam() failed"); - return false; - } - PCERT_INFO pSignerCertInfo = reinterpret_cast(pSignerCertInfoBuf.get()); - - // Open a certificate store in memory using CERT_STORE_PROV_MSG, which - // initializes it with the certificates from the message. - HCERTSTORE hStoreHandle = CertOpenStore(CERT_STORE_PROV_MSG, - PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, - NULL, - 0, - hMsg); - if (!hStoreHandle) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: CertOpenStore() failed"); - return false; - } - - // Find the signer's certificate in the store. - PCCERT_CONTEXT pSignerCertContext = CertGetSubjectCertificateFromStore(hStoreHandle, - PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, - pSignerCertInfo); - if (!pSignerCertContext) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: CertGetSubjectCertificateFromStore() failed"); - return false; - } - else - { - // Write rInformation.ouX509Certificate. - uno::Sequence aDerCert(pSignerCertContext->cbCertEncoded); - for (size_t i = 0; i < pSignerCertContext->cbCertEncoded; ++i) - aDerCert[i] = pSignerCertContext->pbCertEncoded[i]; - OUStringBuffer aBuffer; - sax::Converter::encodeBase64(aBuffer, aDerCert); - rInformation.ouX509Certificate = aBuffer.makeStringAndClear(); - } - - if (bNonDetached) - { - // Not a detached signature. - DWORD nContentParam = 0; - if (!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, nullptr, &nContentParam)) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: CryptMsgGetParam() failed"); - return false; - } - - std::vector aContentParam(nContentParam); - if (!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, aContentParam.data(), &nContentParam)) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: CryptMsgGetParam() failed"); - return false; - } - - if (VerifyNonDetachedSignature(rStream, aByteRanges, aContentParam)) - rInformation.nStatus = xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; - } - else - { - // Detached, the usual case. - // Use the CERT_INFO from the signer certificate to verify the signature. - if (CryptMsgControl(hMsg, 0, CMSG_CTRL_VERIFY_SIGNATURE, pSignerCertContext->pCertInfo)) - rInformation.nStatus = xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; - } - - // Check if we have a signing certificate attribute. - DWORD nSignedAttributes = 0; - if (CryptMsgGetParam(hMsg, CMSG_SIGNER_AUTH_ATTR_PARAM, 0, nullptr, &nSignedAttributes)) - { - std::unique_ptr pSignedAttributesBuf(new BYTE[nSignedAttributes]); - if (!CryptMsgGetParam(hMsg, CMSG_SIGNER_AUTH_ATTR_PARAM, 0, pSignedAttributesBuf.get(), &nSignedAttributes)) - { - SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: CryptMsgGetParam() failed"); - return false; - } - auto pSignedAttributes = reinterpret_cast(pSignedAttributesBuf.get()); - for (size_t nAttr = 0; nAttr < pSignedAttributes->cAttr; ++nAttr) - { - CRYPT_ATTRIBUTE& rAttr = pSignedAttributes->rgAttr[nAttr]; - /* - * id-aa-signingCertificateV2 OBJECT IDENTIFIER ::= - * { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9) - * smime(16) id-aa(2) 47 } - */ - if (OString("1.2.840.113549.1.9.16.2.47") == rAttr.pszObjId) - { - rInformation.bHasSigningCertificate = true; - break; - } - } - } - - CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG); - CryptMsgClose(hMsg); - return true; -#else - // Not implemented. - (void)rStream; - (void)rInformation; - - return false; -#endif + return svl::crypto::Signing::Verify(rStream, aByteRanges, bNonDetached, aSignature, rInformation); } } // namespace pdfio diff --git a/xmlsecurity/workben/pdfverify.cxx b/xmlsecurity/workben/pdfverify.cxx index 8a14f7bf3402..673eb0171050 100644 --- a/xmlsecurity/workben/pdfverify.cxx +++ b/xmlsecurity/workben/pdfverify.cxx @@ -23,7 +23,7 @@ #include -#include +#include using namespace com::sun::star; -- cgit