From e9b5a306a7c1f1d57281e616c773c109aa292760 Mon Sep 17 00:00:00 2001
From: Chinmoy Ranjan Pradhan <chinmoyrp65@protonmail.com>
Date: Wed, 27 Jun 2018 17:16:50 +0000
Subject: [PATCH] Add CertificateInfo to qt interface.

---
 qt5/src/poppler-form.cc | 166 +++++++++++++++++++++++++++++++++++++++-
 qt5/src/poppler-form.h  | 114 +++++++++++++++++++++++++++
 2 files changed, 279 insertions(+), 1 deletion(-)

diff --git a/qt5/src/poppler-form.cc b/qt5/src/poppler-form.cc
index 9d1b329a..7976d86f 100644
--- a/qt5/src/poppler-form.cc
+++ b/qt5/src/poppler-form.cc
@@ -42,6 +42,7 @@
 
 #ifdef ENABLE_NSS3
   #include <hasht.h>
+  #include <certt.h>
 #endif
 
 namespace {
@@ -495,9 +496,139 @@ bool FormFieldChoice::canBeSpellChecked() const
 }
 
 
+struct CertificateInfoPrivate {
+        QByteArray certificate_der;
+        QByteArray serial_number;
+        QByteArray public_key;
+        QByteArray version;
+        QDateTime validity_start;
+        QDateTime validity_end;
+        QString issuer_name;
+        QString issuer_dn;
+        int pub_key_type;
+        int pub_key_strength;
+        int key_usages;
+};
+
+CertificateInfo::CertificateInfo(CertificateInfoPrivate* priv)
+  : d_ptr(priv)
+{
+}
+
+CertificateInfo::CertificateInfo(const CertificateInfo &other)
+ : d_ptr( other.d_ptr )
+{
+}
+
+CertificateInfo::~CertificateInfo()
+{
+}
+
+CertificateInfo &CertificateInfo::operator=(const CertificateInfo &other)
+{
+  if ( this != &other )
+    d_ptr = other.d_ptr;
+
+  return *this;
+}
+
+QByteArray CertificateInfo::version() const
+{
+  Q_D(const CertificateInfo);
+  return d->version;
+}
+
+QString CertificateInfo::issuerName() const
+{
+  Q_D(const CertificateInfo);
+  return d->issuer_name;
+}
+
+QString CertificateInfo::issuerDN() const
+{
+  Q_D(const CertificateInfo);
+  return d->issuer_dn;
+}
+
+QByteArray CertificateInfo::serialNumber() const
+{
+  Q_D(const CertificateInfo);
+  return d->serial_number;
+}
+
+QDateTime CertificateInfo::validityStart() const
+{
+  Q_D(const CertificateInfo);
+  return d->validity_start;
+}
+
+QDateTime CertificateInfo::validityEnd() const
+{
+  Q_D(const CertificateInfo);
+  return d->validity_end;
+}
+
+CertificateInfo::KeyUsages CertificateInfo::keyUsages() const
+{
+    Q_D(const CertificateInfo);
+
+    KeyUsages keyUsages = KuNone;
+    if (d->key_usages & KU_DIGITAL_SIGNATURE)
+        keyUsages |= KuDigitalSignature;
+    if (d->key_usages & KU_NON_REPUDIATION)
+        keyUsages |= KuNonRepudiation;
+    if (d->key_usages & KU_KEY_ENCIPHERMENT)
+        keyUsages |= KuKeyEncipherment;
+    if (d->key_usages & KU_DATA_ENCIPHERMENT)
+        keyUsages |= KuDataEncipherment;
+    if (d->key_usages & KU_KEY_AGREEMENT)
+        keyUsages |= KuKeyAgreement;
+    if (d->key_usages & KU_KEY_CERT_SIGN)
+        keyUsages |= KuKeyCertSign;
+    if (d->key_usages & KU_CRL_SIGN)
+        keyUsages |= KuClrSign;
+    if (d->key_usages & KU_ENCIPHER_ONLY)
+        keyUsages |= KuEncipherOnly;
+
+    return keyUsages;
+}
+
+QByteArray CertificateInfo::publicKey() const
+{
+  Q_D(const CertificateInfo);
+  return d->public_key;
+}
+
+CertificateInfo::PublicKeyType CertificateInfo::publicKeyType() const
+{
+  Q_D(const CertificateInfo);
+  switch (d->pub_key_type)
+  {
+    case RsaKey:
+    case DsaKey:
+    case EcKey:
+      return static_cast<PublicKeyType>(d->pub_key_type);
+    default:
+      return OtherKey;
+  }
+}
+
+int CertificateInfo::publicKeyStrength() const
+{
+  Q_D(const CertificateInfo);
+  return publicKeyType() != OtherKey ? d->pub_key_strength : -1;
+}
+
+QByteArray CertificateInfo::certificateData() const
+{
+  Q_D(const CertificateInfo);
+  return d->certificate_der;
+}
+
 struct SignatureValidationInfoPrivate {
 	SignatureValidationInfo::SignatureStatus signature_status;
 	SignatureValidationInfo::CertificateStatus certificate_status;
+        QSharedPointer<CertificateInfo> cert_info;
 
 	QByteArray signature;
 	QString signer_name;
@@ -515,7 +646,7 @@ SignatureValidationInfo::SignatureValidationInfo(SignatureValidationInfoPrivate*
 }
 
 SignatureValidationInfo::SignatureValidationInfo(const SignatureValidationInfo &other)
- : d_ptr( other.d_ptr )
+ : d_ptr(other.d_ptr)
 {
 }
 
@@ -612,6 +743,12 @@ bool SignatureValidationInfo::signsTotalDocument() const
   return false;
 }
 
+CertificateInfo SignatureValidationInfo::certificateInfo() const
+{
+    Q_D(const SignatureValidationInfo);
+    return *(d->cert_info.data());
+}
+
 SignatureValidationInfo &SignatureValidationInfo::operator=(const SignatureValidationInfo &other)
 {
   if ( this != &other )
@@ -732,6 +869,33 @@ SignatureValidationInfo FormFieldSignature::validate(int opt, const QDateTime& v
   }
   delete checkedSignature;
 
+  // set certificate info
+  X509CertificateInfo* ci = si->getCertificateInfo();
+  CertificateInfoPrivate* certPriv = new CertificateInfoPrivate;
+  certPriv->issuer_name = ci->getIssuerName();
+  certPriv->issuer_dn = ci->getIssuerDN();
+  certPriv->key_usages = ci->getKeyUsages();
+
+  X509CertificateInfo::CertItem certVersion = ci->getVersion();
+  certPriv->version = QByteArray::fromRawData(certVersion.data, certVersion.len).toHex();
+
+  X509CertificateInfo::CertItem certSerial = ci->getSerialNumber();
+  certPriv->serial_number = QByteArray::fromRawData(certSerial.data, certSerial.len).toHex();
+
+  X509CertificateInfo::CertItem certDer = ci->getCertDER();
+  certPriv->certificate_der = QByteArray::fromRawData(certDer.data, certDer.len);
+
+  X509CertificateInfo::Validity certValidity = ci->getValidity();
+  certPriv->validity_start = QDateTime::fromTime_t(certValidity.notBefore);
+  certPriv->validity_end = QDateTime::fromTime_t(certValidity.notAfter);
+
+  X509CertificateInfo::PublicKeyInfo pkInfo = ci->getPublicKeyInfo();
+  certPriv->public_key = QByteArray::fromRawData(pkInfo.publicKey.data, pkInfo.publicKey.len);
+  certPriv->pub_key_type = pkInfo.publicKeyType;
+  certPriv->pub_key_strength = pkInfo.publicKeyStrength;
+
+  priv->cert_info = QSharedPointer<CertificateInfo>(new CertificateInfo(certPriv));
+
   return SignatureValidationInfo(priv);
 }
 
diff --git a/qt5/src/poppler-form.h b/qt5/src/poppler-form.h
index 2dc3fe71..1bf6cbc7 100644
--- a/qt5/src/poppler-form.h
+++ b/qt5/src/poppler-form.h
@@ -402,6 +402,113 @@ namespace Poppler {
 	Q_DISABLE_COPY(FormFieldChoice)
     };
 
+    /**
+      A helper class to store x509 certificate information.
+
+      \since 0.66
+     */
+    class CertificateInfoPrivate;
+    class POPPLER_QT5_EXPORT CertificateInfo {
+    public:
+
+        /**
+          The algorithm of public key.
+         */
+        enum PublicKeyType
+        {
+            // keep in sync with KeyType in nss/keythi.h
+            RsaKey = 1,
+            DsaKey = 2,
+            EcKey = 6,
+            OtherKey = 100
+        };
+
+        /**
+          Certificate key usage.
+         */
+        enum KeyUsage
+        {
+            KuNone = 0,
+            KuDigitalSignature = 1,
+            KuNonRepudiation = 2,
+            KuKeyEncipherment = 4,
+            KuDataEncipherment = 8,
+            KuKeyAgreement = 16,
+            KuKeyCertSign = 32,
+            KuClrSign = 64,
+            KuEncipherOnly = 128
+        };
+        Q_DECLARE_FLAGS(KeyUsages, KeyUsage)
+
+        CertificateInfo(CertificateInfoPrivate *priv);
+        ~CertificateInfo();
+
+        /**
+          The certificate version string.
+         */
+        QByteArray version() const;
+
+        /**
+          The common name of certificate issuer.
+         */
+        QString issuerName() const;
+
+        /**
+          The distinguished name of certificate issuer.
+         */
+        QString issuerDN() const;
+
+        /**
+          The hex encoded certificate serial number.
+         */
+        QByteArray serialNumber() const;
+
+        /**
+          The date-time when certificate becomes valid.
+         */
+        QDateTime validityStart() const;
+
+        /**
+          The date-time when certificate expires.
+         */
+        QDateTime validityEnd() const;
+
+        /**
+          The key usages of certificate.
+         */
+        KeyUsages keyUsages() const;
+
+        /**
+          The public key value.
+         */
+        QByteArray publicKey() const;
+
+        /**
+          The public key type.
+         */
+        PublicKeyType publicKeyType() const;
+
+        /**
+          The strength of public key in bits or -1 in case
+          key type is 'OtherKey'.
+         */
+        int publicKeyStrength() const;
+
+        /**
+          The DER encoded certificate.
+         */
+        QByteArray certificateData() const;
+
+        CertificateInfo(const CertificateInfo &other);
+        CertificateInfo &operator=(const CertificateInfo &other);
+
+        private:
+        Q_DECLARE_PRIVATE(CertificateInfo)
+
+        QSharedPointer<CertificateInfoPrivate> d_ptr;
+    };
+    Q_DECLARE_OPERATORS_FOR_FLAGS(CertificateInfo::KeyUsages)
+
     /**
       A signature validation info helper class.
 
@@ -509,6 +616,13 @@ namespace Poppler {
 	 */
         bool signsTotalDocument() const;
 
+        /**
+          The signer certificate info.
+
+          \since 0.66
+         */
+        CertificateInfo certificateInfo() const;
+
 	SignatureValidationInfo(const SignatureValidationInfo &other);
 	SignatureValidationInfo &operator=(const SignatureValidationInfo &other);
 
-- 
2.17.0

