mirror of https://github.com/JakubMelka/PDF4QT.git
Verifying signature data (first part)
This commit is contained in:
parent
9714fdf25c
commit
f6c5431770
|
@ -21,6 +21,8 @@
|
||||||
#include "pdfform.h"
|
#include "pdfform.h"
|
||||||
#include "pdfsignaturehandler_impl.h"
|
#include "pdfsignaturehandler_impl.h"
|
||||||
|
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QMutexLocker>
|
#include <QMutexLocker>
|
||||||
|
|
||||||
|
@ -255,6 +257,36 @@ void PDFSignatureVerificationResult::addCertificateOtherError(int error)
|
||||||
m_errors << PDFTranslationContext::tr("Certificate validation failed with code %1.").arg(error);
|
m_errors << PDFTranslationContext::tr("Certificate validation failed with code %1.").arg(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFSignatureVerificationResult::addInvalidSignatureError()
|
||||||
|
{
|
||||||
|
m_flags.setFlag(Error_Signature_Invalid);
|
||||||
|
m_errors << PDFTranslationContext::tr("Signature is invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFSignatureVerificationResult::addSignatureNoSignaturesFoundError()
|
||||||
|
{
|
||||||
|
m_flags.setFlag(Error_Signature_NoSignaturesFound);
|
||||||
|
m_errors << PDFTranslationContext::tr("No signatures found in certificate.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFSignatureVerificationResult::addSignatureCertificateMissingError()
|
||||||
|
{
|
||||||
|
m_flags.setFlag(Error_Signature_SourceCertificateMissing);
|
||||||
|
m_errors << PDFTranslationContext::tr("Signature certificate is missing.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFSignatureVerificationResult::addSignatureDigestFailureError()
|
||||||
|
{
|
||||||
|
m_flags.setFlag(Error_Signature_DigestFailure);
|
||||||
|
m_errors << PDFTranslationContext::tr("Signed data has different hash function digest.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFSignatureVerificationResult::addSignatureDataOtherError()
|
||||||
|
{
|
||||||
|
m_flags.setFlag(Error_Signature_DataOther);
|
||||||
|
m_errors << PDFTranslationContext::tr("Signed data are invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
void PDFSignatureVerificationResult::setSignatureFieldQualifiedName(const QString& signatureFieldQualifiedName)
|
void PDFSignatureVerificationResult::setSignatureFieldQualifiedName(const QString& signatureFieldQualifiedName)
|
||||||
{
|
{
|
||||||
m_signatureFieldQualifiedName = signatureFieldQualifiedName;
|
m_signatureFieldQualifiedName = signatureFieldQualifiedName;
|
||||||
|
@ -428,6 +460,92 @@ void PDFPublicKeySignatureHandler::verifyCertificate(PDFSignatureVerificationRes
|
||||||
void PDFPublicKeySignatureHandler::verifySignature(PDFSignatureVerificationResult& result) const
|
void PDFPublicKeySignatureHandler::verifySignature(PDFSignatureVerificationResult& result) const
|
||||||
{
|
{
|
||||||
PDFOpenSSLGlobalLock lock;
|
PDFOpenSSLGlobalLock lock;
|
||||||
|
|
||||||
|
OpenSSL_add_all_algorithms();
|
||||||
|
|
||||||
|
const PDFSignature& signature = m_signatureField->getSignature();
|
||||||
|
const QByteArray& content = signature.getContents();
|
||||||
|
|
||||||
|
// Jakub Melka: we will try to get pkcs7 from signature, then
|
||||||
|
// verify signer certificates.
|
||||||
|
const unsigned char* data = reinterpret_cast<const unsigned char*>(content.data());
|
||||||
|
if (PKCS7* pkcs7 = d2i_PKCS7(nullptr, &data, content.size()))
|
||||||
|
{
|
||||||
|
if (BIO* inputBuffer = getSignedDataBuffer(result))
|
||||||
|
{
|
||||||
|
if (BIO* dataBio = PKCS7_dataInit(pkcs7, inputBuffer))
|
||||||
|
{
|
||||||
|
// Now, we must read from bio to calculate digests (digest is returned)
|
||||||
|
std::array<char, 16384> buffer = { };
|
||||||
|
int bytesRead = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
bytesRead = BIO_read(dataBio, buffer.data(), int(buffer.size()));
|
||||||
|
} while (bytesRead > 0);
|
||||||
|
|
||||||
|
STACK_OF(PKCS7_SIGNER_INFO)* signerInfo = PKCS7_get_signer_info(pkcs7);
|
||||||
|
const int signerInfoCount = sk_PKCS7_SIGNER_INFO_num(signerInfo);
|
||||||
|
STACK_OF(X509)* certificates = getCertificates(pkcs7);
|
||||||
|
if (signerInfo && signerInfoCount > 0 && certificates)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < signerInfoCount; ++i)
|
||||||
|
{
|
||||||
|
PKCS7_SIGNER_INFO* signerInfoValue = sk_PKCS7_SIGNER_INFO_value(signerInfo, i);
|
||||||
|
PKCS7_ISSUER_AND_SERIAL* issuerAndSerial = signerInfoValue->issuer_and_serial;
|
||||||
|
X509* signer = X509_find_by_issuer_and_serial(certificates, issuerAndSerial->issuer, issuerAndSerial->serial);
|
||||||
|
|
||||||
|
if (!signer)
|
||||||
|
{
|
||||||
|
result.addSignatureCertificateMissingError();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int verification = PKCS7_signatureVerify(dataBio, pkcs7, signerInfoValue, signer);
|
||||||
|
if (verification <= 0)
|
||||||
|
{
|
||||||
|
const int reason = ERR_GET_REASON(ERR_get_error());
|
||||||
|
switch (reason)
|
||||||
|
{
|
||||||
|
case PKCS7_R_DIGEST_FAILURE:
|
||||||
|
result.addSignatureDigestFailureError();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
result.addSignatureDataOtherError();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.addSignatureNoSignaturesFoundError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// According to the documentation, we should not call PKCS7_dataFinal
|
||||||
|
// at the end, when pkcs7 is populated.
|
||||||
|
|
||||||
|
BIO_free(dataBio);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.addInvalidSignatureError();
|
||||||
|
}
|
||||||
|
|
||||||
|
BIO_free(inputBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
PKCS7_free(pkcs7);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.addInvalidSignatureError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.hasSignatureError())
|
||||||
|
{
|
||||||
|
result.setFlag(PDFSignatureVerificationResult::Signature_OK, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFSignatureVerificationResult PDFSignatureHandler_adbe_pkcs7_detached::verify() const
|
PDFSignatureVerificationResult PDFSignatureHandler_adbe_pkcs7_detached::verify() const
|
||||||
|
|
|
@ -247,27 +247,36 @@ public:
|
||||||
|
|
||||||
enum VerificationFlag
|
enum VerificationFlag
|
||||||
{
|
{
|
||||||
None = 0x00000, ///< Used only for initialization
|
None = 0x00000, ///< Used only for initialization
|
||||||
OK = 0x00001, ///< Both certificate and signature is OK
|
OK = 0x00001, ///< Both certificate and signature is OK
|
||||||
Certificate_OK = 0x00002, ///< Certificate is OK
|
Certificate_OK = 0x00002, ///< Certificate is OK
|
||||||
Signature_OK = 0x00004, ///< Signature is OK
|
Signature_OK = 0x00004, ///< Signature is OK
|
||||||
Error_NoHandler = 0x00008, ///< No signature handler for given signature
|
Error_NoHandler = 0x00008, ///< No signature handler for given signature
|
||||||
Error_Generic = 0x00010, ///< Generic error (uknown general error)
|
Error_Generic = 0x00010, ///< Generic error (uknown general error)
|
||||||
|
|
||||||
Error_Certificate_Invalid = 0x00020, ///< Certificate is invalid
|
Error_Certificate_Invalid = 0x00020, ///< Certificate is invalid
|
||||||
Error_Certificate_NoSignatures = 0x00040, ///< No signature found in certificate data
|
Error_Certificate_NoSignatures = 0x00040, ///< No signature found in certificate data
|
||||||
Error_Certificate_Missing = 0x00080, ///< Certificate is missing
|
Error_Certificate_Missing = 0x00080, ///< Certificate is missing
|
||||||
Error_Certificate_Generic = 0x00100, ///< Generic error during certificate verification
|
Error_Certificate_Generic = 0x00100, ///< Generic error during certificate verification
|
||||||
Error_Certificate_Expired = 0x00200, ///< Certificate has expired
|
Error_Certificate_Expired = 0x00200, ///< Certificate has expired
|
||||||
Error_Certificate_SelfSigned = 0x00400, ///< Self signed certificate
|
Error_Certificate_SelfSigned = 0x00400, ///< Self signed certificate
|
||||||
Error_Certificate_SelfSignedChain = 0x00800, ///< Self signed certificate in chain
|
Error_Certificate_SelfSignedChain = 0x00800, ///< Self signed certificate in chain
|
||||||
Error_Certificate_TrustedNotFound = 0x01000, ///< No trusted certificate was found
|
Error_Certificate_TrustedNotFound = 0x01000, ///< No trusted certificate was found
|
||||||
Error_Certificate_Revoked = 0x02000, ///< Certificate has been revoked
|
Error_Certificate_Revoked = 0x02000, ///< Certificate has been revoked
|
||||||
Error_Certificate_Other = 0x04000, ///< Other certificate error. See OpenSSL code for details.
|
Error_Certificate_Other = 0x04000, ///< Other certificate error. See OpenSSL code for details.
|
||||||
|
|
||||||
|
Error_Signature_Invalid = 0x08000, ///< Signature is invalid for some reason
|
||||||
|
Error_Signature_SourceCertificateMissing = 0x10000, ///< Source certificate of signature is missing
|
||||||
|
Error_Signature_NoSignaturesFound = 0x20000, ///< No signatures found
|
||||||
|
Error_Signature_DigestFailure = 0x40000, ///< Digest failure
|
||||||
|
Error_Signature_DataOther = 0x80000, ///< Signed data were not verified
|
||||||
|
|
||||||
Error_Certificates_Mask = Error_Certificate_Invalid | Error_Certificate_NoSignatures | Error_Certificate_Missing | Error_Certificate_Generic |
|
Error_Certificates_Mask = Error_Certificate_Invalid | Error_Certificate_NoSignatures | Error_Certificate_Missing | Error_Certificate_Generic |
|
||||||
Error_Certificate_Expired | Error_Certificate_SelfSigned | Error_Certificate_SelfSignedChain | Error_Certificate_TrustedNotFound |
|
Error_Certificate_Expired | Error_Certificate_SelfSigned | Error_Certificate_SelfSignedChain | Error_Certificate_TrustedNotFound |
|
||||||
Error_Certificate_Revoked | Error_Certificate_Other
|
Error_Certificate_Revoked | Error_Certificate_Other,
|
||||||
|
|
||||||
|
Error_Signatures_Mask = Error_Signature_Invalid | Error_Signature_SourceCertificateMissing | Error_Signature_NoSignaturesFound |
|
||||||
|
Error_Signature_DigestFailure | Error_Signature_DataOther,
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(VerificationFlags, VerificationFlag)
|
Q_DECLARE_FLAGS(VerificationFlags, VerificationFlag)
|
||||||
|
|
||||||
|
@ -285,12 +294,18 @@ public:
|
||||||
void addCertificateTrustedNotFoundError();
|
void addCertificateTrustedNotFoundError();
|
||||||
void addCertificateRevokedError();
|
void addCertificateRevokedError();
|
||||||
void addCertificateOtherError(int error);
|
void addCertificateOtherError(int error);
|
||||||
|
void addInvalidSignatureError();
|
||||||
|
void addSignatureNoSignaturesFoundError();
|
||||||
|
void addSignatureCertificateMissingError();
|
||||||
|
void addSignatureDigestFailureError();
|
||||||
|
void addSignatureDataOtherError();
|
||||||
|
|
||||||
bool isValid() const { return hasFlag(OK); }
|
bool isValid() const { return hasFlag(OK); }
|
||||||
bool isCertificateValid() const { return hasFlag(Certificate_OK); }
|
bool isCertificateValid() const { return hasFlag(Certificate_OK); }
|
||||||
bool isSignatureValid() const { return hasFlag(Signature_OK); }
|
bool isSignatureValid() const { return hasFlag(Signature_OK); }
|
||||||
bool hasError() const { return !isValid(); }
|
bool hasError() const { return !isValid(); }
|
||||||
bool hasCertificateError() const { return m_flags & Error_Certificates_Mask; }
|
bool hasCertificateError() const { return m_flags & Error_Certificates_Mask; }
|
||||||
|
bool hasSignatureError() const { return m_flags & Error_Signatures_Mask; }
|
||||||
bool hasFlag(VerificationFlag flag) const { return m_flags.testFlag(flag); }
|
bool hasFlag(VerificationFlag flag) const { return m_flags.testFlag(flag); }
|
||||||
void setFlag(VerificationFlag flag, bool value) { m_flags.setFlag(flag, value); }
|
void setFlag(VerificationFlag flag, bool value) { m_flags.setFlag(flag, value); }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue