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
This commit is contained in:
Ingo Klöcker 2024-05-15 10:31:46 +02:00
parent ac4bf86bb6
commit adadfac997
No known key found for this signature in database
GPG Key ID: F5A5D1692277A1E9
7 changed files with 151 additions and 1 deletions

4
NEWS
View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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. */

View File

@ -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);

View File

@ -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)