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 <[email protected]> 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()); } } }
