aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Klöcker <[email protected]>2024-05-15 08:31:46 +0000
committerIngo Klöcker <[email protected]>2024-05-21 14:38:59 +0000
commitadadfac997a812699049cd9a5f484cbcabff5bfd (patch)
tree41b5c964ed1396b20ede6968379708cc21802faf
parenttests: Fix segv in t-json.c (diff)
downloadgpgme-adadfac997a812699049cd9a5f484cbcabff5bfd.tar.gz
gpgme-adadfac997a812699049cd9a5f484cbcabff5bfd.zip
core: Add information about revocation keys to keys
* src/gpgme.h.in (struct _gpgme_revocation_key, gpgme_revocation_key_t): New. (struct _gpgme_key): Add fields 'revkeys', '_last_revkey'. * src/key.c (_gpgme_key_add_rev_key): New. (gpgme_key_unref): Free revkeys. * src/keylist.c (keylist_colon_handler): Parse rvk lines. * src/ops.h (_gpgme_key_add_rev_key): New. * tests/run-keylist.c (main): Print revocation key info. -- GnuPG-bug-id: 7118
-rw-r--r--NEWS4
-rw-r--r--doc/gpgme.texi35
-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/run-keylist.c9
7 files changed, 151 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index f2e715f1..ae79ce93 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@ 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]
+
* qt: Allow reading the data to decrypt/encrypt/sign/verify directly from
files. [T6550]
@@ -17,6 +19,8 @@ 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.
qt: DecryptVerifyJob::setInputFile NEW.
diff --git a/doc/gpgme.texi b/doc/gpgme.texi
index bdac95a3..aaa2ab3f 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/src/gpgme.h.in b/src/gpgme.h.in
index c8eba0a5..eaeb22aa 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/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)