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 "pdfsignaturehandler_impl.h"
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
|
||||
|
@ -255,6 +257,36 @@ void PDFSignatureVerificationResult::addCertificateOtherError(int 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)
|
||||
{
|
||||
m_signatureFieldQualifiedName = signatureFieldQualifiedName;
|
||||
|
@ -428,6 +460,92 @@ void PDFPublicKeySignatureHandler::verifyCertificate(PDFSignatureVerificationRes
|
|||
void PDFPublicKeySignatureHandler::verifySignature(PDFSignatureVerificationResult& result) const
|
||||
{
|
||||
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
|
||||
|
|
|
@ -247,27 +247,36 @@ public:
|
|||
|
||||
enum VerificationFlag
|
||||
{
|
||||
None = 0x00000, ///< Used only for initialization
|
||||
OK = 0x00001, ///< Both certificate and signature is OK
|
||||
Certificate_OK = 0x00002, ///< Certificate is OK
|
||||
Signature_OK = 0x00004, ///< Signature is OK
|
||||
Error_NoHandler = 0x00008, ///< No signature handler for given signature
|
||||
Error_Generic = 0x00010, ///< Generic error (uknown general error)
|
||||
None = 0x00000, ///< Used only for initialization
|
||||
OK = 0x00001, ///< Both certificate and signature is OK
|
||||
Certificate_OK = 0x00002, ///< Certificate is OK
|
||||
Signature_OK = 0x00004, ///< Signature is OK
|
||||
Error_NoHandler = 0x00008, ///< No signature handler for given signature
|
||||
Error_Generic = 0x00010, ///< Generic error (uknown general error)
|
||||
|
||||
Error_Certificate_Invalid = 0x00020, ///< Certificate is invalid
|
||||
Error_Certificate_NoSignatures = 0x00040, ///< No signature found in certificate data
|
||||
Error_Certificate_Missing = 0x00080, ///< Certificate is missing
|
||||
Error_Certificate_Generic = 0x00100, ///< Generic error during certificate verification
|
||||
Error_Certificate_Expired = 0x00200, ///< Certificate has expired
|
||||
Error_Certificate_SelfSigned = 0x00400, ///< Self signed certificate
|
||||
Error_Certificate_SelfSignedChain = 0x00800, ///< Self signed certificate in chain
|
||||
Error_Certificate_TrustedNotFound = 0x01000, ///< No trusted certificate was found
|
||||
Error_Certificate_Revoked = 0x02000, ///< Certificate has been revoked
|
||||
Error_Certificate_Other = 0x04000, ///< Other certificate error. See OpenSSL code for details.
|
||||
Error_Certificate_Invalid = 0x00020, ///< Certificate is invalid
|
||||
Error_Certificate_NoSignatures = 0x00040, ///< No signature found in certificate data
|
||||
Error_Certificate_Missing = 0x00080, ///< Certificate is missing
|
||||
Error_Certificate_Generic = 0x00100, ///< Generic error during certificate verification
|
||||
Error_Certificate_Expired = 0x00200, ///< Certificate has expired
|
||||
Error_Certificate_SelfSigned = 0x00400, ///< Self signed certificate
|
||||
Error_Certificate_SelfSignedChain = 0x00800, ///< Self signed certificate in chain
|
||||
Error_Certificate_TrustedNotFound = 0x01000, ///< No trusted certificate was found
|
||||
Error_Certificate_Revoked = 0x02000, ///< Certificate has been revoked
|
||||
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_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)
|
||||
|
||||
|
@ -285,12 +294,18 @@ public:
|
|||
void addCertificateTrustedNotFoundError();
|
||||
void addCertificateRevokedError();
|
||||
void addCertificateOtherError(int error);
|
||||
void addInvalidSignatureError();
|
||||
void addSignatureNoSignaturesFoundError();
|
||||
void addSignatureCertificateMissingError();
|
||||
void addSignatureDigestFailureError();
|
||||
void addSignatureDataOtherError();
|
||||
|
||||
bool isValid() const { return hasFlag(OK); }
|
||||
bool isCertificateValid() const { return hasFlag(Certificate_OK); }
|
||||
bool isSignatureValid() const { return hasFlag(Signature_OK); }
|
||||
bool hasError() const { return !isValid(); }
|
||||
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); }
|
||||
void setFlag(VerificationFlag flag, bool value) { m_flags.setFlag(flag, value); }
|
||||
|
||||
|
|
Loading…
Reference in New Issue