aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Klöcker <[email protected]>2024-05-24 08:47:15 +0000
committerIngo Klöcker <[email protected]>2024-05-24 08:47:15 +0000
commitf0d1f2c4c746d6f98643772b4864c09f3642cd83 (patch)
tree6348dacfbb5f42e946902dc42436d165fb8df904
parentqt,cpp: Implement adding ADSKs to existing keys (diff)
parentcpp: Add information about revocation keys to Key (diff)
downloadgpgme-f0d1f2c4c746d6f98643772b4864c09f3642cd83.tar.gz
gpgme-f0d1f2c4c746d6f98643772b4864c09f3642cd83.zip
Merge branch 'ikloecker/t7118-revkeys'
-rw-r--r--NEWS11
-rw-r--r--doc/gpgme.texi35
-rw-r--r--lang/cpp/src/gpgmefw.h3
-rw-r--r--lang/cpp/src/key.cpp107
-rw-r--r--lang/cpp/src/key.h49
-rw-r--r--lang/cpp/tests/run-keylist.cpp5
-rw-r--r--src/gpgme-json.c28
-rw-r--r--src/gpgme.h.in28
-rw-r--r--src/key.c38
-rw-r--r--src/keylist.c37
-rw-r--r--src/ops.h1
-rw-r--r--tests/json/Makefile.am6
-rw-r--r--tests/json/key-with-revokers.asc19
-rw-r--r--tests/json/t-json.c1
-rw-r--r--tests/json/t-keylist-revokers.in.json5
-rw-r--r--tests/json/t-keylist-revokers.out.json97
-rw-r--r--tests/run-keylist.c9
17 files changed, 476 insertions, 3 deletions
diff --git a/NEWS b/NEWS
index f2e715f1..b7309454 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,11 @@ Noteworthy changes in version 1.24.0 (unrelease)
* Extended gpgme_op_encrypt*, gpgme_op_encrypt_sign*, and gpgme_op_sign*
to allow reading the input data directly from a file. [T6550]
+ * 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]
@@ -17,8 +22,14 @@ Noteworthy changes in version 1.24.0 (unrelease)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GPGME_ENCRYPT_FILE NEW.
GPGME_SIG_MODE_FILE NEW.
+ gpgme_key_t EXTENDED: New field 'revkeys'.
+ 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/doc/gpgme.texi b/doc/gpgme.texi
index 258ef0a5..48cca032 100644
--- a/doc/gpgme.texi
+++ b/doc/gpgme.texi
@@ -3566,6 +3566,10 @@ be missing but this field may be set nevertheless.
Reserved for the time of the last update of this key.
+@item gpgme_revocation_key_t revkeys
+@since{1.24.0}
+This is a linked list with the revocation keys for the key.
+
@end table
@end deftp
@@ -3908,6 +3912,37 @@ This is a linked list with the notation data and policy URLs.
@end deftp
+@deftp {Data type} gpgme_revocation_key_t
+@since{1.24.0}
+
+The @code{gpgme_revocation_key_t} type is a pointer to a revocation key
+structure. Revocation key structures are one component of a
+@code{gpgme_key_t} object. They provide information about the designated
+revocation keys for a key.
+
+The revocation key structure has the following members:
+
+@table @code
+@item gpgme_revocation_key_t next
+This is a pointer to the next revocation key structure in the linked list,
+or @code{NULL} if this is the last element.
+
+@item gpgme_pubkey_algo_t pubkey_algo
+This is the public key algorithm of the revocation key.
+
+@item char *fpr
+This is the fingerprint of the revocation_key in hexadecimal digits.
+
+@item unsigned int key_class
+This is the class of the revocation key signature subpacket.
+
+@item unsigned int sensitive : 1
+This is true if the revocation key is marked as sensitive.
+
+@end table
+@end deftp
+
+
@node Listing Keys
@subsection Listing Keys
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<Subkey> 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<RevocationKey> Key::revocationKeys() const
+{
+ if (!key) {
+ return std::vector<RevocationKey>();
+ }
+
+ std::vector<RevocationKey> 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<Subkey> subkeys = key.subkeys();
std::copy(subkeys.begin(), subkeys.end(),
std::ostream_iterator<Subkey>(os, "\n"));
+ os << " revocationKeys:\n";
+ const std::vector<RevocationKey> revkeys = key.revocationKeys();
+ std::copy(revkeys.begin(), revkeys.end(),
+ std::ostream_iterator<RevocationKey>(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<gpgme_key_t>::type > shared_gpgme_key_t;
@@ -100,6 +101,10 @@ public:
std::vector<UserID> userIDs() const;
std::vector<Subkey> subkeys() const;
+ RevocationKey revocationKey(unsigned int index) const;
+ unsigned int numRevocationKeys() const;
+ std::vector<RevocationKey> 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();
diff --git a/src/gpgme-json.c b/src/gpgme-json.c
index 3d18eee2..c88973a8 100644
--- a/src/gpgme-json.c
+++ b/src/gpgme-json.c
@@ -1024,6 +1024,24 @@ subkey_to_json (gpgme_subkey_t sub)
return result;
}
+/* Create a revocation key json object */
+static cjson_t
+revocation_key_to_json (gpgme_revocation_key_t revkey)
+{
+ cjson_t result = xjson_CreateObject ();
+
+ xjson_AddBoolToObject (result, "sensitive", revkey->sensitive);
+
+ xjson_AddStringToObject0 (result, "fingerprint", revkey->fpr);
+ xjson_AddStringToObject0 (result, "pubkey_algo_name",
+ gpgme_pubkey_algo_name (revkey->pubkey_algo));
+
+ xjson_AddNumberToObject (result, "pubkey_algo", revkey->pubkey_algo);
+ xjson_AddNumberToObject (result, "key_class", revkey->key_class);
+
+ return result;
+}
+
/* Create a key json object */
static cjson_t
key_to_json (gpgme_key_t key)
@@ -1075,6 +1093,16 @@ key_to_json (gpgme_key_t key)
xjson_AddItemToObject (result, "userids", uid_array);
}
+ /* Revocation keys */
+ if (key->revocation_keys)
+ {
+ gpgme_revocation_key_t revkey;
+ cjson_t array = xjson_CreateArray ();
+ for (revkey = key->revocation_keys; revkey; revkey = revkey->next)
+ cJSON_AddItemToArray (array, revocation_key_to_json (revkey));
+ xjson_AddItemToObject (result, "revocation_keys", array);
+ }
+
return result;
}
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index bfd6f72b..0ee3e088 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -763,6 +763,28 @@ struct _gpgme_user_id
typedef struct _gpgme_user_id *gpgme_user_id_t;
+/* A designated revocation key for a key.
+ * This structure shall be considered read-only and an application
+ * must not allocate such a structure on its own. */
+struct _gpgme_revocation_key
+{
+ struct _gpgme_revocation_key *next;
+
+ /* The public key algorithm of the revocation key. */
+ gpgme_pubkey_algo_t pubkey_algo;
+
+ /* The fingerprint of the revocation_key in hex digit form. */
+ char *fpr;
+
+ /* The class of the revocation key. */
+ unsigned int key_class;
+
+ /* True if the revocation key should not be exported. */
+ unsigned int sensitive : 1;
+};
+typedef struct _gpgme_revocation_key *gpgme_revocation_key_t;
+
+
/* A key from the keyring.
* This structure shall be considered read-only and an application
* must not allocate such a structure on its own. */
@@ -860,6 +882,12 @@ struct _gpgme_key
/* Time of the last refresh of the entire key. 0 if unknown. */
unsigned long last_update;
+
+ /* The revocation keys of the key. */
+ gpgme_revocation_key_t revocation_keys;
+
+ /* Internal to GPGME, do not use. */
+ gpgme_revocation_key_t _last_revkey;
};
typedef struct _gpgme_key *gpgme_key_t;
diff --git a/src/key.c b/src/key.c
index 93cdc1c8..fec9eb16 100644
--- a/src/key.c
+++ b/src/key.c
@@ -304,6 +304,35 @@ _gpgme_key_add_sig (gpgme_key_t key, char *src)
}
+gpgme_error_t
+_gpgme_key_add_rev_key (gpgme_key_t key, const char *src)
+{
+ gpgme_revocation_key_t revkey;
+ int src_len = src ? strlen (src) : 0;
+
+ assert (key);
+ /* malloc a buffer for the revocation key and the fingerprint. */
+ revkey = malloc (sizeof (*revkey) + src_len + 1);
+ if (!revkey)
+ return gpg_error_from_syserror ();
+ memset (revkey, 0, sizeof *revkey);
+
+ revkey->fpr = ((char *) revkey) + sizeof (*revkey);
+ if (src)
+ memcpy (revkey->fpr, src, src_len + 1);
+ else
+ revkey->fpr[0] = '\0';
+
+ if (!key->revocation_keys)
+ key->revocation_keys = revkey;
+ if (key->_last_revkey)
+ key->_last_revkey->next = revkey;
+ key->_last_revkey = revkey;
+
+ return 0;
+}
+
+
/* Acquire a reference to KEY. */
void
gpgme_key_ref (gpgme_key_t key)
@@ -324,6 +353,7 @@ gpgme_key_unref (gpgme_key_t key)
{
gpgme_user_id_t uid;
gpgme_subkey_t subkey;
+ gpgme_revocation_key_t revkey;
if (!key)
return;
@@ -392,6 +422,14 @@ gpgme_key_unref (gpgme_key_t key)
uid = next_uid;
}
+ revkey = key->revocation_keys;
+ while (revkey)
+ {
+ gpgme_revocation_key_t next = revkey->next;
+ free (revkey);
+ revkey = next;
+ }
+
free (key->issuer_serial);
free (key->issuer_name);
free (key->chain_id);
diff --git a/src/keylist.c b/src/keylist.c
index 1d8c8184..f8dd2962 100644
--- a/src/keylist.c
+++ b/src/keylist.c
@@ -603,7 +603,7 @@ keylist_colon_handler (void *priv, char *line)
enum
{
RT_NONE, RT_SIG, RT_UID, RT_TFS, RT_SUB, RT_PUB, RT_FPR, RT_FP2, RT_GRP,
- RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK
+ RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK, RT_RVK
}
rectype = RT_NONE;
#define NR_FIELDS 20
@@ -669,6 +669,8 @@ keylist_colon_handler (void *priv, char *line)
rectype = RT_SSB;
else if (!strcmp (field[0], "spk") && key)
rectype = RT_SPK;
+ else if (!strcmp (field[0], "rvk") && key)
+ rectype = RT_RVK;
else
rectype = RT_NONE;
@@ -1124,6 +1126,39 @@ keylist_colon_handler (void *priv, char *line)
keysig->_last_notation = notation;
}
}
+ break;
+
+ case RT_RVK:
+ /* Ignore revocation keys without fingerprint */
+ if (fields >= 10 && *field[9])
+ {
+ gpgme_revocation_key_t revkey = NULL;
+
+ err = _gpgme_key_add_rev_key (key, field[9]);
+ if (err)
+ return err;
+
+ revkey = key->_last_revkey;
+ assert (revkey);
+
+ /* Field 4 has the public key algorithm. */
+ {
+ int i = atoi (field[3]);
+ if (i >= 1 && i < 128)
+ revkey->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol);
+ }
+
+ /* Field 11 has the class (eg, 0x40 means sensitive). */
+ if (fields >= 11 && field[10][0] && field[10][1])
+ {
+ int key_class = _gpgme_hextobyte (field[10]);
+ if (key_class >= 0)
+ revkey->key_class = key_class;
+ if (field[10][2] == 's')
+ revkey->sensitive = 1;
+ }
+ }
+ break;
case RT_NONE:
/* Unknown record. */
diff --git a/src/ops.h b/src/ops.h
index cde63a4e..aa8d9c94 100644
--- a/src/ops.h
+++ b/src/ops.h
@@ -145,6 +145,7 @@ gpgme_error_t _gpgme_key_add_subkey (gpgme_key_t key,
gpgme_error_t _gpgme_key_append_name (gpgme_key_t key,
const char *src, int convert);
gpgme_key_sig_t _gpgme_key_add_sig (gpgme_key_t key, char *src);
+gpgme_error_t _gpgme_key_add_rev_key (gpgme_key_t key, const char *src);
diff --git a/tests/json/Makefile.am b/tests/json/Makefile.am
index 90fba79e..0484cb74 100644
--- a/tests/json/Makefile.am
+++ b/tests/json/Makefile.am
@@ -88,9 +88,13 @@ gpg-sample.stamp: $(private_keys)
done
echo x > ./gpg-sample.stamp
-pubring-stamp: $(top_srcdir)/tests/gpg/pubdemo.asc gpg-sample.stamp
+pubring-stamp: $(top_srcdir)/tests/gpg/pubdemo.asc \
+ $(top_srcdir)/tests/json/key-with-revokers.asc \
+ gpg-sample.stamp
$(TESTS_ENVIRONMENT) $(GPG) --batch --no-permission-warning \
--import $(top_srcdir)/tests/gpg/pubdemo.asc
+ $(TESTS_ENVIRONMENT) $(GPG) --batch --no-permission-warning \
+ --import $(top_srcdir)/tests/json/key-with-revokers.asc
-$(TESTS_ENVIRONMENT) $(GPG) --batch --no-permission-warning \
--import $(top_srcdir)/tests/gpg/secdemo.asc
-$(TESTS_ENVIRONMENT) gpgconf --kill all
diff --git a/tests/json/key-with-revokers.asc b/tests/json/key-with-revokers.asc
new file mode 100644
index 00000000..3fa9011c
--- /dev/null
+++ b/tests/json/key-with-revokers.asc
@@ -0,0 +1,19 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mDMEZkTFQxYJKwYBBAHaRw8BAQdATFay6x2u19PsF5P7YDj2WW9KproKIqAMAqHR
+cnkiebiIkAQfFgoAOBYhBMlchkt3X3HQL1LO9r0HuCiy91BxBQJmRMVDFwzAEaD/
+RZC7YSLt7248VC1yfMdoaXc0AgcAAAoJEL0HuCiy91BxhCMBAKtymj/0Q/XDKO3c
+9mlz5ycll8MfT/a6H2WFWGV6L9SEAPwN3/n4qR9bBiReT9Xo3q58e2efoXoFXz86
+BXv1rCYJAYiQBB8WCgA4FiEEyVyGS3dfcdAvUs72vQe4KLL3UHEFAmZExUMXDIAR
+I/00ekGUKbrM1ecta8R3gFSs0kYCBwAACgkQvQe4KLL3UHFlBwEA1JL4yE/sWOKr
+BfbHbUI4ffS6s+oh7sQxHEQy0pJN7LoA/RSKUIThOl5apOVhd/dYOPj+4aGZ9ZP1
+ARqeXIWYxpwCtB1rZXktd2l0aC1yZXZva2Vyc0BleGFtcGxlLm5ldIiZBBMWCgBB
+FiEEyVyGS3dfcdAvUs72vQe4KLL3UHEFAmZExUMCGwMFCQWjmoAFCwkIBwICIgIG
+FQoJCAsCBBYCAwECHgcCF4AACgkQvQe4KLL3UHFcjwD/ZpSNHKpGV99sKlxbzABg
+msIGKLgcuFLUsT1QCV3yE4cA/iS4NW9Y508uUqoJfFH0lBpJ4+US6VQevVpRNe6N
+KqYEuDgEZkTFQxIKKwYBBAGXVQEFAQEHQFDZXf9Y1Y6A00CDcYw8RO73idcn/d7B
+ifTuBfYpXVJjAwEIB4h4BBgWCgAgFiEEyVyGS3dfcdAvUs72vQe4KLL3UHEFAmZE
+xUMCGwwACgkQvQe4KLL3UHEZrQD/SWYkwCFtqaxbYQUcSJ+v2+wA28RUm7KrgJ+A
+PsdiNJsBAIjUUsYlf+J/d4Ia0tccfzPBqVpyeWZ52bBD0pH/Eu8N
+=JTll
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/json/t-json.c b/tests/json/t-json.c
index 4fe74ed7..80aeaabc 100644
--- a/tests/json/t-json.c
+++ b/tests/json/t-json.c
@@ -41,6 +41,7 @@ static const char*tests[] = { "t-config", "t-version",
"t-encrypt", "t-encrypt-sign", "t-sign", "t-verify",
"t-decrypt-verify", "t-export", "t-createkey",
"t-export-secret-info", "t-chunking", "t-sig-notations",
+ "t-keylist-revokers",
/* For these two the order is important
* as t-import imports the deleted key from t-delete */
"t-delete", "t-import",
diff --git a/tests/json/t-keylist-revokers.in.json b/tests/json/t-keylist-revokers.in.json
new file mode 100644
index 00000000..a3f28296
--- /dev/null
+++ b/tests/json/t-keylist-revokers.in.json
@@ -0,0 +1,5 @@
+{
+ "op": "keylist",
+ "keys": [ "[email protected]" ],
+ "with-secret": false
+}
diff --git a/tests/json/t-keylist-revokers.out.json b/tests/json/t-keylist-revokers.out.json
new file mode 100644
index 00000000..be8f633b
--- /dev/null
+++ b/tests/json/t-keylist-revokers.out.json
@@ -0,0 +1,97 @@
+{
+ "keys": [
+ {
+ "revoked": false,
+ "expired": false,
+ "disabled": false,
+ "invalid": false,
+ "can_encrypt": true,
+ "can_sign": true,
+ "can_certify": true,
+ "can_authenticate": false,
+ "secret": false,
+ "is_qualified": false,
+ "protocol": "OpenPGP",
+ "fingerprint": "C95C864B775F71D02F52CEF6BD07B828B2F75071",
+ "owner_trust": "unknown",
+ "origin": 0,
+ "last_update": 0,
+ "subkeys": [
+ {
+ "revoked": false,
+ "expired": false,
+ "disabled": false,
+ "invalid": false,
+ "can_encrypt": false,
+ "can_sign": true,
+ "can_certify": true,
+ "can_authenticate": false,
+ "secret": false,
+ "is_qualified": false,
+ "is_cardkey": false,
+ "is_de_vs": false,
+ "pubkey_algo_name": "EdDSA",
+ "pubkey_algo_string": "ed25519",
+ "keyid": "BD07B828B2F75071",
+ "curve": "ed25519",
+ "pubkey_algo": 303,
+ "length": 255,
+ "timestamp": 1715782979,
+ "expires": 1810390979
+ },
+ {
+ "revoked": false,
+ "expired": false,
+ "disabled": false,
+ "invalid": false,
+ "can_encrypt": true,
+ "can_sign": false,
+ "can_certify": false,
+ "can_authenticate": false,
+ "secret": false,
+ "is_qualified": false,
+ "is_cardkey": false,
+ "is_de_vs": false,
+ "pubkey_algo_name": "ECDH",
+ "pubkey_algo_string": "cv25519",
+ "keyid": "94C2E4C722CADAF9",
+ "curve": "cv25519",
+ "pubkey_algo": 302,
+ "length": 255,
+ "timestamp": 1715782979,
+ "expires": 0
+ }
+ ],
+ "userids": [
+ {
+ "revoked": false,
+ "invalid": false,
+ "validity": "unknown",
+ "uid": "[email protected]",
+ "name": "",
+ "email": "[email protected]",
+ "comment": "",
+ "address": "[email protected]",
+ "origin": 0,
+ "last_update": 0
+ }
+ ],
+ "revocation_keys": [
+ {
+ "sensitive": true,
+ "fingerprint": "A0FF4590BB6122EDEF6E3C542D727CC768697734",
+ "pubkey_algo_name": "DSA",
+ "pubkey_algo": 17,
+ "key_class": 192
+ },
+ {
+ "sensitive": false,
+ "fingerprint": "23FD347A419429BACCD5E72D6BC4778054ACD246",
+ "pubkey_algo_name": "DSA",
+ "pubkey_algo": 17,
+ "key_class": 128
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/run-keylist.c b/tests/run-keylist.c
index a9d4b6aa..9ecf380b 100644
--- a/tests/run-keylist.c
+++ b/tests/run-keylist.c
@@ -308,9 +308,11 @@ main (int argc, char **argv)
gpgme_user_id_t uid;
gpgme_tofu_info_t ti;
gpgme_key_sig_t ks;
+ gpgme_revocation_key_t revkey;
int nuids;
int nsub;
int nsigs;
+ int nrevkeys;
printf ("keyid : %s\n", key->subkeys?nonnull (key->subkeys->keyid):"?");
printf ("can_cap : %s%s%s%s\n",
@@ -425,6 +427,13 @@ main (int argc, char **argv)
}
}
+ revkey = key->revocation_keys;
+ for (nrevkeys=0; revkey; revkey = revkey->next, nrevkeys++)
+ {
+ printf ("revkey%2d: %s\n", nrevkeys, revkey->fpr);
+ printf (" class: %x\n", revkey->key_class);
+ }
+
putchar ('\n');
if (import)