[poppler] poppler/CertificateInfo.cc poppler/CertificateInfo.h poppler/GPGMECryptoSignBackend.cc qt5/src qt6/src utils/pdfsig.cc

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Aug 2 22:39:29 UTC 2023


 poppler/CertificateInfo.cc        |   11 ++++++++++-
 poppler/CertificateInfo.h         |   19 +++++++++++++++++++
 poppler/GPGMECryptoSignBackend.cc |    7 +++++++
 qt5/src/poppler-form.cc           |   23 +++++++++++++++++++++++
 qt5/src/poppler-form.h            |   25 +++++++++++++++++++++++++
 qt6/src/poppler-form.cc           |   23 +++++++++++++++++++++++
 qt6/src/poppler-form.h            |   25 +++++++++++++++++++++++++
 utils/pdfsig.cc                   |   18 +++++++++++++++++-
 8 files changed, 149 insertions(+), 2 deletions(-)

New commits:
commit 7dedced88e354625ef3f4dc09c9732a4d91cf5d7
Author: Sune Vuorela <sune at vuorela.dk>
Date:   Wed Aug 2 22:39:27 2023 +0000

    Provide the key location for certificates you can sign with

diff --git a/poppler/CertificateInfo.cc b/poppler/CertificateInfo.cc
index b6a8437a..d4ae8f64 100644
--- a/poppler/CertificateInfo.cc
+++ b/poppler/CertificateInfo.cc
@@ -17,7 +17,7 @@
 #include <cstring>
 #include <cstdlib>
 
-X509CertificateInfo::X509CertificateInfo() : ku_extensions(KU_NONE), cert_version(-1), is_self_signed(false) { }
+X509CertificateInfo::X509CertificateInfo() : ku_extensions(KU_NONE), cert_version(-1), is_self_signed(false), keyLocation(KeyLocation::Unknown) { }
 
 X509CertificateInfo::~X509CertificateInfo() = default;
 
@@ -120,3 +120,12 @@ void X509CertificateInfo::setIsSelfSigned(bool isSelfSigned)
 {
     is_self_signed = isSelfSigned;
 }
+KeyLocation X509CertificateInfo::getKeyLocation() const
+{
+    return keyLocation;
+}
+
+void X509CertificateInfo::setKeyLocation(KeyLocation location)
+{
+    keyLocation = location;
+}
diff --git a/poppler/CertificateInfo.h b/poppler/CertificateInfo.h
index 600ecb52..d2dbc34f 100644
--- a/poppler/CertificateInfo.h
+++ b/poppler/CertificateInfo.h
@@ -41,6 +41,22 @@ enum PublicKeyType
     OTHERKEY
 };
 
+/** A signing key can be located in different places
+ sometimes. For the user, it might be easier to pick
+ the key located on a card if it has some visual
+ indicator that it is somehow removable.
+
+ \note a keylocation for a certificate without a private
+ key (cannot be used for signing) will likely be "Unknown"
+ */
+enum class KeyLocation
+{
+    Unknown, /** We don't know the location */
+    Other, /** We know the location, but it is somehow not covered by this enum */
+    Computer, /** The key is on this computer */
+    HardwareToken /** The key is on a dedicated hardware token, either a smartcard or a dedicated usb token (e.g. gnuk, nitrokey or yubikey) */
+};
+
 class POPPLER_PRIVATE_EXPORT X509CertificateInfo
 {
 public:
@@ -101,6 +117,7 @@ public:
     unsigned int getKeyUsageExtensions() const;
     const GooString &getCertificateDER() const;
     bool getIsSelfSigned() const;
+    KeyLocation getKeyLocation() const;
 
     /* SETTERS */
     void setVersion(int);
@@ -113,6 +130,7 @@ public:
     void setKeyUsageExtensions(unsigned int);
     void setCertificateDER(const GooString &);
     void setIsSelfSigned(bool);
+    void setKeyLocation(KeyLocation location);
 
 private:
     EntityInfo issuer_info;
@@ -125,6 +143,7 @@ private:
     unsigned int ku_extensions;
     int cert_version;
     bool is_self_signed;
+    KeyLocation keyLocation;
 };
 
 #endif
diff --git a/poppler/GPGMECryptoSignBackend.cc b/poppler/GPGMECryptoSignBackend.cc
index 6f82e266..273cce0e 100644
--- a/poppler/GPGMECryptoSignBackend.cc
+++ b/poppler/GPGMECryptoSignBackend.cc
@@ -153,6 +153,13 @@ static std::unique_ptr<X509CertificateInfo> getCertificateInfoFromKey(const GpgM
     }
     certificateInfo->setKeyUsageExtensions(kue);
 
+    auto subkey = key.subkey(0);
+    if (subkey.isCardKey()) {
+        certificateInfo->setKeyLocation(KeyLocation::HardwareToken);
+    } else if (subkey.isSecret()) {
+        certificateInfo->setKeyLocation(KeyLocation::Computer);
+    }
+
     return certificateInfo;
 }
 
diff --git a/qt5/src/poppler-form.cc b/qt5/src/poppler-form.cc
index d46b5b42..08c91c33 100644
--- a/qt5/src/poppler-form.cc
+++ b/qt5/src/poppler-form.cc
@@ -610,6 +610,7 @@ public:
     int version;
     bool is_self_signed;
     bool is_null;
+    CertificateInfo::KeyLocation keyLocation;
 };
 
 CertificateInfo::CertificateInfo() : d_ptr(new CertificateInfoPrivate())
@@ -735,6 +736,12 @@ CertificateInfo::KeyUsageExtensions CertificateInfo::keyUsageExtensions() const
     return kuExtensions;
 }
 
+CertificateInfo::KeyLocation CertificateInfo::keyLocation() const
+{
+    Q_D(const CertificateInfo);
+    return d->keyLocation;
+}
+
 QByteArray CertificateInfo::publicKey() const
 {
     Q_D(const CertificateInfo);
@@ -971,6 +978,21 @@ SignatureValidationInfo FormFieldSignature::validate(ValidateOptions opt) const
     return validate(opt, QDateTime());
 }
 
+static CertificateInfo::KeyLocation fromPopplerCore(KeyLocation location)
+{
+    switch (location) {
+    case KeyLocation::Computer:
+        return CertificateInfo::KeyLocation::Computer;
+    case KeyLocation::Other:
+        return CertificateInfo::KeyLocation::Other;
+    case KeyLocation::Unknown:
+        return CertificateInfo::KeyLocation::Unknown;
+    case KeyLocation::HardwareToken:
+        return CertificateInfo::KeyLocation::HardwareToken;
+    }
+    return CertificateInfo::KeyLocation::Unknown;
+}
+
 static CertificateInfoPrivate *createCertificateInfoPrivate(const X509CertificateInfo *ci)
 {
     CertificateInfoPrivate *certPriv = new CertificateInfoPrivate;
@@ -978,6 +1000,7 @@ static CertificateInfoPrivate *createCertificateInfoPrivate(const X509Certificat
     if (ci) {
         certPriv->version = ci->getVersion();
         certPriv->ku_extensions = ci->getKeyUsageExtensions();
+        certPriv->keyLocation = fromPopplerCore(ci->getKeyLocation());
 
         const GooString &certSerial = ci->getSerialNumber();
         certPriv->serial_number = QByteArray(certSerial.c_str(), certSerial.getLength());
diff --git a/qt5/src/poppler-form.h b/qt5/src/poppler-form.h
index 9599a855..ad4fa2c3 100644
--- a/qt5/src/poppler-form.h
+++ b/qt5/src/poppler-form.h
@@ -535,6 +535,24 @@ public:
         Organization,
     };
 
+    /** A signing key can be located in different places
+     sometimes. For the user, it might be easier to pick
+     the key located on a card if it has some visual
+     indicator that it is somehow removable.
+
+     \note a keylocation for a certificate without a private
+     key (cannot be used for signing) will likely be "Unknown"
+
+     \since 23.09
+     */
+    enum class KeyLocation
+    {
+        Unknown, /** We don't know the location */
+        Other, /** We know the location, but it is somehow not covered by this enum */
+        Computer, /** The key is on this computer */
+        HardwareToken /** The key is on a dedicated hardware token, either a smartcard or a dedicated usb token (e.g. gnuk, nitrokey or yubikey) */
+    };
+
     CertificateInfo();
     explicit CertificateInfo(CertificateInfoPrivate *priv);
     ~CertificateInfo();
@@ -618,6 +636,13 @@ public:
      */
     bool checkPassword(const QString &password) const;
 
+    /**
+     The storage location for this key
+
+     \since 23.09
+     */
+    KeyLocation keyLocation() const;
+
     CertificateInfo(const CertificateInfo &other);
     CertificateInfo &operator=(const CertificateInfo &other);
 
diff --git a/qt6/src/poppler-form.cc b/qt6/src/poppler-form.cc
index 94fc06e0..781e9546 100644
--- a/qt6/src/poppler-form.cc
+++ b/qt6/src/poppler-form.cc
@@ -610,6 +610,7 @@ public:
     int version;
     bool is_self_signed;
     bool is_null;
+    CertificateInfo::KeyLocation keyLocation;
 };
 
 CertificateInfo::CertificateInfo() : d_ptr(new CertificateInfoPrivate())
@@ -735,6 +736,12 @@ CertificateInfo::KeyUsageExtensions CertificateInfo::keyUsageExtensions() const
     return kuExtensions;
 }
 
+CertificateInfo::KeyLocation CertificateInfo::keyLocation() const
+{
+    Q_D(const CertificateInfo);
+    return d->keyLocation;
+}
+
 QByteArray CertificateInfo::publicKey() const
 {
     Q_D(const CertificateInfo);
@@ -971,6 +978,21 @@ SignatureValidationInfo FormFieldSignature::validate(ValidateOptions opt) const
     return validate(opt, QDateTime());
 }
 
+static CertificateInfo::KeyLocation fromPopplerCore(KeyLocation location)
+{
+    switch (location) {
+    case KeyLocation::Computer:
+        return CertificateInfo::KeyLocation::Computer;
+    case KeyLocation::Other:
+        return CertificateInfo::KeyLocation::Other;
+    case KeyLocation::Unknown:
+        return CertificateInfo::KeyLocation::Unknown;
+    case KeyLocation::HardwareToken:
+        return CertificateInfo::KeyLocation::HardwareToken;
+    }
+    return CertificateInfo::KeyLocation::Unknown;
+}
+
 static CertificateInfoPrivate *createCertificateInfoPrivate(const X509CertificateInfo *ci)
 {
     CertificateInfoPrivate *certPriv = new CertificateInfoPrivate;
@@ -978,6 +1000,7 @@ static CertificateInfoPrivate *createCertificateInfoPrivate(const X509Certificat
     if (ci) {
         certPriv->version = ci->getVersion();
         certPriv->ku_extensions = ci->getKeyUsageExtensions();
+        certPriv->keyLocation = fromPopplerCore(ci->getKeyLocation());
 
         const GooString &certSerial = ci->getSerialNumber();
         certPriv->serial_number = QByteArray(certSerial.c_str(), certSerial.getLength());
diff --git a/qt6/src/poppler-form.h b/qt6/src/poppler-form.h
index 2915df6c..7bd4105d 100644
--- a/qt6/src/poppler-form.h
+++ b/qt6/src/poppler-form.h
@@ -501,6 +501,24 @@ public:
         Organization,
     };
 
+    /** A signing key can be located in different places
+     sometimes. For the user, it might be easier to pick
+     the key located on a card if it has some visual
+     indicator that it is somehow removable.
+
+     \note a keylocation for a certificate without a private
+     key (cannot be used for signing) will likely be "Unknown"
+
+     \since 23.09
+     */
+    enum class KeyLocation
+    {
+        Unknown, /** We don't know the location */
+        Other, /** We know the location, but it is somehow not covered by this enum */
+        Computer, /** The key is on this computer */
+        HardwareToken /** The key is on a dedicated hardware token, either a smartcard or a dedicated usb token (e.g. gnuk, nitrokey or yubikey) */
+    };
+
     CertificateInfo();
     explicit CertificateInfo(CertificateInfoPrivate *priv);
     ~CertificateInfo();
@@ -584,6 +602,13 @@ public:
      */
     bool checkPassword(const QString &password) const;
 
+    /**
+     The storage location for this key
+
+     \since 23.09
+     */
+    KeyLocation keyLocation() const;
+
     CertificateInfo(const CertificateInfo &other);
     CertificateInfo &operator=(const CertificateInfo &other);
 
diff --git a/utils/pdfsig.cc b/utils/pdfsig.cc
index 7e6c7e8b..1c016847 100644
--- a/utils/pdfsig.cc
+++ b/utils/pdfsig.cc
@@ -256,6 +256,21 @@ static std::vector<std::unique_ptr<X509CertificateInfo>> getAvailableSigningCert
     return vCerts;
 }
 
+static std::string locationToString(KeyLocation location)
+{
+    switch (location) {
+    case KeyLocation::Unknown:
+        return {};
+    case KeyLocation::Other:
+        return "(Other)";
+    case KeyLocation::Computer:
+        return "(Computer)";
+    case KeyLocation::HardwareToken:
+        return "(Hardware Token)";
+    }
+    return {};
+}
+
 static std::string TextStringToUTF8(const std::string &str)
 {
     const UnicodeMap *utf8Map = globalParams->getUtf8Map();
@@ -329,7 +344,8 @@ int main(int argc, char *argv[])
                 printf("Certificate nicknames available:\n");
                 for (auto &cert : vCerts) {
                     const GooString &nick = cert->getNickName();
-                    printf("%s\n", nick.c_str());
+                    const auto location = locationToString(cert->getKeyLocation());
+                    printf("%s %s\n", nick.c_str(), location.c_str());
                 }
             }
         }


More information about the poppler mailing list