poppler/Form.cc | 8 ++++---- poppler/Form.h | 4 ++-- poppler/SignatureHandler.cc | 12 +++++++++--- poppler/SignatureHandler.h | 2 +- qt5/src/poppler-form.cc | 2 +- qt5/src/poppler-form.h | 3 ++- qt6/src/poppler-form.cc | 2 +- qt6/src/poppler-form.h | 3 ++- utils/pdfsig.1 | 3 +++ utils/pdfsig.cc | 4 +++- 10 files changed, 28 insertions(+), 15 deletions(-)
New commits: commit e5516f8c1827862a7e650dd850b0e919a2d6c51e Author: Theofilos Intzoglou <[email protected]> Date: Mon Sep 27 10:07:05 2021 +0000 Add support for AIA fetching to verify certificates diff --git a/poppler/Form.cc b/poppler/Form.cc index 2e1bbc98..354c9f8e 100644 --- a/poppler/Form.cc +++ b/poppler/Form.cc @@ -538,9 +538,9 @@ const GooString *FormWidgetSignature::getSignature() const return static_cast<FormFieldSignature *>(field)->getSignature(); } -SignatureInfo *FormWidgetSignature::validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime, bool ocspRevocationCheck) +SignatureInfo *FormWidgetSignature::validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime, bool ocspRevocationCheck, bool enableAIA) { - return static_cast<FormFieldSignature *>(field)->validateSignature(doVerifyCert, forceRevalidation, validationTime, ocspRevocationCheck); + return static_cast<FormFieldSignature *>(field)->validateSignature(doVerifyCert, forceRevalidation, validationTime, ocspRevocationCheck, enableAIA); } #ifdef ENABLE_NSS3 @@ -2141,7 +2141,7 @@ void FormWidgetSignature::setSignatureType(FormSignatureType fst) static_cast<FormFieldSignature *>(field)->setSignatureType(fst); } -SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime, bool ocspRevocationCheck) +SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime, bool ocspRevocationCheck, bool enableAIA) { #ifdef ENABLE_NSS3 if (signature_info->getSignatureValStatus() != SIGNATURE_NOT_VERIFIED && !forceRevalidation) { @@ -2212,7 +2212,7 @@ SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool for return signature_info; } - const CertificateValidationStatus cert_val_state = signature_handler.validateCertificate(validationTime, ocspRevocationCheck); + const CertificateValidationStatus cert_val_state = signature_handler.validateCertificate(validationTime, ocspRevocationCheck, enableAIA); signature_info->setCertificateValStatus(cert_val_state); signature_info->setCertificateInfo(signature_handler.getCertificateInfo()); diff --git a/poppler/Form.h b/poppler/Form.h index 572b035f..6489b0dd 100644 --- a/poppler/Form.h +++ b/poppler/Form.h @@ -296,7 +296,7 @@ public: void setSignatureType(FormSignatureType fst); // Use -1 for now as validationTime - SignatureInfo *validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime, bool ocspRevocationCheck); + SignatureInfo *validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime, bool ocspRevocationCheck, bool enableAIA); // returns a list with the boundaries of the signed ranges // the elements of the list are of type Goffset @@ -596,7 +596,7 @@ public: FormFieldSignature(PDFDoc *docA, Object &&dict, const Ref ref, FormField *parent, std::set<int> *usedParents); // Use -1 for now as validationTime - SignatureInfo *validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime, bool ocspRevocationCheck); + SignatureInfo *validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime, bool ocspRevocationCheck, bool enableAIA); // returns a list with the boundaries of the signed ranges // the elements of the list are of type Goffset diff --git a/poppler/SignatureHandler.cc b/poppler/SignatureHandler.cc index f4a3bbc5..f3af96ce 100644 --- a/poppler/SignatureHandler.cc +++ b/poppler/SignatureHandler.cc @@ -944,7 +944,7 @@ SignatureValidationStatus SignatureHandler::validateSignature() } } -CertificateValidationStatus SignatureHandler::validateCertificate(time_t validation_time, bool ocspRevocationCheck) +CertificateValidationStatus SignatureHandler::validateCertificate(time_t validation_time, bool ocspRevocationCheck, bool useAIACertFetch) { CERTCertificate *cert; @@ -957,7 +957,7 @@ CertificateValidationStatus SignatureHandler::validateCertificate(time_t validat PRTime vTime = 0; // time in microseconds since the epoch, special value 0 means now if (validation_time > 0) vTime = 1000000 * (PRTime)validation_time; - CERTValInParam inParams[3]; + CERTValInParam inParams[4]; inParams[0].type = cert_pi_revocationFlags; if (ocspRevocationCheck) { inParams[0].value.pointer.revocation = CERT_GetClassicOCSPEnabledSoftFailurePolicy(); @@ -966,7 +966,13 @@ CertificateValidationStatus SignatureHandler::validateCertificate(time_t validat } inParams[1].type = cert_pi_date; inParams[1].value.scalar.time = vTime; - inParams[2].type = cert_pi_end; + if (useAIACertFetch) { + inParams[2].type = cert_pi_useAIACertFetch; + inParams[2].value.scalar.b = PR_TRUE; + inParams[3].type = cert_pi_end; + } else { + inParams[2].type = cert_pi_end; + } CERT_PKIXVerifyCert(cert, certificateUsageEmailSigner, inParams, nullptr, CMSSignerInfo->cmsg->pwfn_arg); diff --git a/poppler/SignatureHandler.h b/poppler/SignatureHandler.h index 32277898..c18a897f 100644 --- a/poppler/SignatureHandler.h +++ b/poppler/SignatureHandler.h @@ -55,7 +55,7 @@ public: void restartHash(); SignatureValidationStatus validateSignature(); // Use -1 as validation_time for now - CertificateValidationStatus validateCertificate(time_t validation_time, bool ocspRevocationCheck); + CertificateValidationStatus validateCertificate(time_t validation_time, bool ocspRevocationCheck, bool useAIACertFetch); std::unique_ptr<X509CertificateInfo> getCertificateInfo() const; static std::vector<std::unique_ptr<X509CertificateInfo>> getAvailableSigningCertificates(); std::unique_ptr<GooString> signDetached(const char *password) const; diff --git a/qt5/src/poppler-form.cc b/qt5/src/poppler-form.cc index b07f97e2..1d2ef539 100644 --- a/qt5/src/poppler-form.cc +++ b/qt5/src/poppler-form.cc @@ -980,7 +980,7 @@ SignatureValidationInfo FormFieldSignature::validate(int opt, const QDateTime &v { FormWidgetSignature *fws = static_cast<FormWidgetSignature *>(m_formData->fm); const time_t validationTimeT = validationTime.isValid() ? validationTime.toSecsSinceEpoch() : -1; - SignatureInfo *si = fws->validateSignature(opt & ValidateVerifyCertificate, opt & ValidateForceRevalidation, validationTimeT, !(opt & ValidateWithoutOCSPRevocationCheck)); + SignatureInfo *si = fws->validateSignature(opt & ValidateVerifyCertificate, opt & ValidateForceRevalidation, validationTimeT, !(opt & ValidateWithoutOCSPRevocationCheck), opt & ValidateUseAIACertFetch); // get certificate info const X509CertificateInfo *ci = si->getCertificateInfo(); diff --git a/qt5/src/poppler-form.h b/qt5/src/poppler-form.h index dce89632..a07f689c 100644 --- a/qt5/src/poppler-form.h +++ b/qt5/src/poppler-form.h @@ -787,7 +787,8 @@ public: { ValidateVerifyCertificate = 1, ///< Validate the certificate. ValidateForceRevalidation = 2, ///< Force revalidation of the certificate. - ValidateWithoutOCSPRevocationCheck = 4 ///< Do not contact OCSP servers to check for certificate revocation status \since 21.10 + ValidateWithoutOCSPRevocationCheck = 4, ///< Do not contact OCSP servers to check for certificate revocation status \since 21.10 + ValidateUseAIACertFetch = 8 ///< Use the AIA extension for certificate fetching \since 21.10 }; /// \cond PRIVATE diff --git a/qt6/src/poppler-form.cc b/qt6/src/poppler-form.cc index cc947055..eb651528 100644 --- a/qt6/src/poppler-form.cc +++ b/qt6/src/poppler-form.cc @@ -980,7 +980,7 @@ SignatureValidationInfo FormFieldSignature::validate(int opt, const QDateTime &v { FormWidgetSignature *fws = static_cast<FormWidgetSignature *>(m_formData->fm); const time_t validationTimeT = validationTime.isValid() ? validationTime.toSecsSinceEpoch() : -1; - SignatureInfo *si = fws->validateSignature(opt & ValidateVerifyCertificate, opt & ValidateForceRevalidation, validationTimeT, !(opt & ValidateWithoutOCSPRevocationCheck)); + SignatureInfo *si = fws->validateSignature(opt & ValidateVerifyCertificate, opt & ValidateForceRevalidation, validationTimeT, !(opt & ValidateWithoutOCSPRevocationCheck), opt & ValidateUseAIACertFetch); // get certificate info const X509CertificateInfo *ci = si->getCertificateInfo(); diff --git a/qt6/src/poppler-form.h b/qt6/src/poppler-form.h index 94b75c9d..441c31e9 100644 --- a/qt6/src/poppler-form.h +++ b/qt6/src/poppler-form.h @@ -739,7 +739,8 @@ public: { ValidateVerifyCertificate = 1, ///< Validate the certificate. ValidateForceRevalidation = 2, ///< Force revalidation of the certificate. - ValidateWithoutOCSPRevocationCheck = 4 ///< Do not contact OCSP servers to check for certificate revocation status \since 21.10 + ValidateWithoutOCSPRevocationCheck = 4, ///< Do not contact OCSP servers to check for certificate revocation status \since 21.10 + ValidateUseAIACertFetch = 8 ///< Use the AIA extension for certificate fetching \since 21.10 }; /// \cond PRIVATE diff --git a/utils/pdfsig.1 b/utils/pdfsig.1 index 09b6be52..7e262009 100644 --- a/utils/pdfsig.1 +++ b/utils/pdfsig.1 @@ -46,6 +46,9 @@ Do not validate the certificate. .B \-no-ocsp Do not perform online OCSP certificate revocation check (local Certificate Revocation Lists (CRL) are still used). .TP +.B \-aia +Enable the use of Authority Information Access (AIA) extension to fetch missing certificates to build the certificate chain. +.TP .B \-dump Dump all signatures into current directory. .TP diff --git a/utils/pdfsig.cc b/utils/pdfsig.cc index 3849387c..d59c5ff0 100644 --- a/utils/pdfsig.cc +++ b/utils/pdfsig.cc @@ -139,12 +139,14 @@ static char digestName[256] = "SHA256"; static GooString reason; static bool listNicknames = false; static bool addNewSignature = false; +static bool useAIACertFetch = false; static GooString newSignatureFieldName; static const ArgDesc argDesc[] = { { "-nssdir", argGooString, &nssDir, 0, "path to directory of libnss3 database" }, { "-nss-pwd", argGooString, &nssPassword, 0, "password to access the NSS database (if any)" }, { "-nocert", argFlag, &dontVerifyCert, 0, "don't perform certificate validation" }, { "-no-ocsp", argFlag, &noOCSPRevocationCheck, 0, "don't perform online OCSP certificate revocation check" }, + { "-aia", argFlag, &useAIACertFetch, 0, "use Authority Information Access (AIA) extension for certificate fetching" }, { "-dump", argFlag, &dumpSignatures, 0, "dump all signatures into current directory" }, { "-add-signature", argFlag, &addNewSignature, 0, "adds a new signature to the document" }, { "-new-signature-field-name", argGooString, &newSignatureFieldName, 0, "field name used for the newly added signature. A random ID will be used if empty" }, @@ -397,7 +399,7 @@ int main(int argc, char *argv[]) } for (unsigned int i = 0; i < sigCount; i++) { - const SignatureInfo *sig_info = signatures.at(i)->validateSignature(!dontVerifyCert, false, -1 /* now */, !noOCSPRevocationCheck); + const SignatureInfo *sig_info = signatures.at(i)->validateSignature(!dontVerifyCert, false, -1 /* now */, !noOCSPRevocationCheck, useAIACertFetch); printf("Signature #%u:\n", i + 1); printf(" - Signer Certificate Common Name: %s\n", sig_info->getSignerName()); printf(" - Signer full Distinguished Name: %s\n", sig_info->getSubjectDN());
