From 90eb80134b2d7720b187a6b7fd16f40f23cf1022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20Kl=C3=B6cker?= Date: Tue, 21 May 2024 16:32:23 +0200 Subject: [PATCH] cpp: Add information about revocation keys to Key * lang/cpp/src/gpgmefw.h (gpgme_revocation_key_t): New forward declaration. * lang/cpp/src/key.cpp, lang/cpp/src/key.h (class Key): New methods revocationKey, numRevocationKeys, revocationKeys. (class RevocationKey): New. (swap): New overload for RevocationKey. (operator<<): New overload for RevocationKey. * lang/cpp/src/key.cpp (operator<<): Add information about revocation keys to the output stream for Key. * lang/cpp/tests/run-keylist.cpp (main): Don't output Key if nextKey failed, e.g. at the end of the key listing. -- GnuPG-bug-id: 7118 --- NEWS | 7 +++ lang/cpp/src/gpgmefw.h | 3 + lang/cpp/src/key.cpp | 107 +++++++++++++++++++++++++++++++++ lang/cpp/src/key.h | 49 +++++++++++++++ lang/cpp/tests/run-keylist.cpp | 5 +- 5 files changed, 170 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index ae79ce93..b7309454 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,9 @@ Noteworthy changes in version 1.24.0 (unrelease) * Add information about designated revocation keys. [T7118] + * cpp: Provide information about designated revocation keys for a Key. + [T7118] + * qt: Allow reading the data to decrypt/encrypt/sign/verify directly from files. [T6550] @@ -23,6 +26,10 @@ Noteworthy changes in version 1.24.0 (unrelease) gpgme_revocation_key_t NEW. cpp: Context::EncryptFile NEW. cpp: SignatureMode::SignFile NEW. + cpp: RevocationKey NEW. + cpp: Key::revocationKey NEW. + cpp: Key::numRevocationKeys NEW. + cpp: Key::revocationKeys NEW. qt: DecryptVerifyJob::setInputFile NEW. qt: DecryptVerifyJob::inputFile NEW. qt: DecryptVerifyJob::setOutputFile NEW. diff --git a/lang/cpp/src/gpgmefw.h b/lang/cpp/src/gpgmefw.h index fdad7bf0..c6166d2c 100644 --- a/lang/cpp/src/gpgmefw.h +++ b/lang/cpp/src/gpgmefw.h @@ -75,4 +75,7 @@ typedef struct _gpgme_tofu_info *gpgme_tofu_info_t; struct _gpgme_op_query_swdb_result; typedef struct _gpgme_op_query_swdb_result *gpgme_query_swdb_result_t; +struct _gpgme_revocation_key; +typedef struct _gpgme_revocation_key *gpgme_revocation_key_t; + #endif // __GPGMEPP_GPGMEFW_H__ diff --git a/lang/cpp/src/key.cpp b/lang/cpp/src/key.cpp index 9cbd188b..2465cf06 100644 --- a/lang/cpp/src/key.cpp +++ b/lang/cpp/src/key.cpp @@ -122,6 +122,37 @@ std::vector Key::subkeys() const return v; } +RevocationKey Key::revocationKey(unsigned int index) const +{ + return RevocationKey(key, index); +} + +unsigned int Key::numRevocationKeys() const +{ + if (!key) { + return 0; + } + unsigned int count = 0; + for (auto revkey = key->revocation_keys; revkey; revkey = revkey->next) { + ++count; + } + return count; +} + +std::vector Key::revocationKeys() const +{ + if (!key) { + return std::vector(); + } + + std::vector v; + v.reserve(numRevocationKeys()); + for (auto revkey = key->revocation_keys; revkey; revkey = revkey->next) { + v.push_back(RevocationKey(key, revkey)); + } + return v; +} + Key::OwnerTrust Key::ownerTrust() const { if (!key) { @@ -1256,6 +1287,68 @@ bool UserID::Signature::isBad() const return isNull() || isExpired() || isInvalid(); } +// +// +// class RevocationKey +// +// + +static gpgme_revocation_key_t find_revkey(const shared_gpgme_key_t &key, unsigned int idx) +{ + if (key) { + for (gpgme_revocation_key_t s = key->revocation_keys; s; s = s->next, --idx) { + if (idx == 0) { + return s; + } + } + } + return nullptr; +} + +static gpgme_revocation_key_t verify_revkey(const shared_gpgme_key_t &key, gpgme_revocation_key_t revkey) +{ + if (key) { + for (gpgme_revocation_key_t s = key->revocation_keys; s; s = s->next) { + if (s == revkey) { + return revkey; + } + } + } + return nullptr; +} + +RevocationKey::RevocationKey() : key(), revkey(nullptr) {} + +RevocationKey::RevocationKey(const shared_gpgme_key_t &k, unsigned int idx) + : key(k), revkey(find_revkey(k, idx)) +{ +} + +RevocationKey::RevocationKey(const shared_gpgme_key_t &k, gpgme_revocation_key_t sk) + : key(k), revkey(verify_revkey(k, sk)) +{ +} + +Key RevocationKey::parent() const +{ + return Key(key); +} + +const char *RevocationKey::fingerprint() const +{ + return revkey ? revkey->fpr : nullptr; +} + +bool RevocationKey::isSensitive() const +{ + return revkey ? revkey->sensitive : false; +} + +int RevocationKey::algorithm() const +{ + return revkey ? revkey->pubkey_algo : 0; +} + std::ostream &operator<<(std::ostream &os, const UserID &uid) { os << "GpgME::UserID("; @@ -1325,6 +1418,20 @@ std::ostream &operator<<(std::ostream &os, const Key &key) const std::vector subkeys = key.subkeys(); std::copy(subkeys.begin(), subkeys.end(), std::ostream_iterator(os, "\n")); + os << " revocationKeys:\n"; + const std::vector revkeys = key.revocationKeys(); + std::copy(revkeys.begin(), revkeys.end(), + std::ostream_iterator(os, "\n")); + } + return os << ')'; +} + +std::ostream &operator<<(std::ostream &os, const RevocationKey &revkey) +{ + os << "GpgME::RevocationKey("; + if (!revkey.isNull()) { + os << "\n fingerprint: " << protect(revkey.fingerprint()) + << "\n isSensitive: " << revkey.isSensitive(); } return os << ')'; } diff --git a/lang/cpp/src/key.h b/lang/cpp/src/key.h index bdcc18d2..a1648884 100644 --- a/lang/cpp/src/key.h +++ b/lang/cpp/src/key.h @@ -44,6 +44,7 @@ class Context; class Subkey; class UserID; class TofuInfo; +class RevocationKey; typedef std::shared_ptr< std::remove_pointer::type > shared_gpgme_key_t; @@ -100,6 +101,10 @@ public: std::vector userIDs() const; std::vector subkeys() const; + RevocationKey revocationKey(unsigned int index) const; + unsigned int numRevocationKeys() const; + std::vector revocationKeys() const; + bool isRevoked() const; bool isExpired() const; bool isDisabled() const; @@ -547,9 +552,53 @@ private: gpgme_key_sig_t sig; }; +// +// class RevocationKey +// + +class GPGMEPP_EXPORT RevocationKey +{ +public: + RevocationKey(); + RevocationKey(const shared_gpgme_key_t &key, gpgme_revocation_key_t revkey); + RevocationKey(const shared_gpgme_key_t &key, unsigned int idx); + + // Rule of Zero + + void swap(RevocationKey &other) + { + using std::swap; + swap(this->key, other.key); + swap(this->revkey, other.revkey); + } + + bool isNull() const + { + return !key || !revkey; + } + + Key parent() const; + + const char *fingerprint() const; + + bool isSensitive() const; + + int algorithm() const; + +private: + shared_gpgme_key_t key; + gpgme_revocation_key_t revkey; +}; + +inline void swap(RevocationKey& v1, RevocationKey& v2) +{ + v1.swap(v2); +} + GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const UserID &uid); GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Subkey &subkey); GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Key &key); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const RevocationKey &revkey); } // namespace GpgME diff --git a/lang/cpp/tests/run-keylist.cpp b/lang/cpp/tests/run-keylist.cpp index 9e7d763c..b46a815a 100644 --- a/lang/cpp/tests/run-keylist.cpp +++ b/lang/cpp/tests/run-keylist.cpp @@ -160,7 +160,10 @@ main (int argc, char **argv) std::stringstream ss; do { key = ctx->nextKey(err); - ss << key << "\n\n"; + if (!err) + { + ss << key << "\n\n"; + } } while (!err && !key.isNull()); std::cout << ss.str();