gpg: Allow adding of Additional Decryption Subkeys.

* g10/free-packet.c (copy_public_key): Factor some code out to ...
(copy_public_key_basics): new.
* g10/build-packet.c (build_sig_subpkt_from_sig): New arg signhints.
* g10/packet.h (PUBKEY_USAGE_RENC): Fix value.
(SIGNHINT_KEYSIG, SIGNHINT_SELFSIG): Moved from sign.c.
(SIGNHINT_ADSK): New.
(PKT_public_key): Change pubkey_usage from byte to u16.
(PKT_user_id): Cosmetic fix: change help_key_usage from int to u16.
* g10/getkey.c (parse_key_usage): Make public.
* g10/misc.c (openpgp_pk_algo_usage): Take PUBKEY_USAGE_RENC in
account.
* g10/sign.c (update_keysig_packet): Set SIGNHINT_ADSK.
(make_keysig_packet): Ditto.
(do_sign): No time warp check in ADSK mode.
* g10/sig-check.c (check_signature_metadata_validity): Ditto.
* g10/keygen.c (struct opaque_data_usage_and_pk): Remove.
(write_keybinding): Do not use the removed struct.
(do_add_key_flags): Support PUBKEY_USAGE_RENC and others.
(keygen_add_key_flags_and_expire): Rewrite and make public.
* g10/keyedit.c (enum cmdids): Add cmdADDADSK.
(keyedit_menu): Add command "addadsk".
(menu_addadsk): New.
--

This makes use of a new encryption flag:

  The "restricted encryption key" (2nd,0x04) does not take part in any
  automatic selection of encryption keys.  It is only found on a
  subkey signature (type 0x18), one that refers to the key the flag
  applies to.

Followup patches will add encryption support and a --quick command.

GnuPG-bug-id: 6395
This commit is contained in:
Werner Koch 2023-03-01 17:22:20 +01:00
parent 1aaadede76
commit 3a18378a92
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
13 changed files with 278 additions and 76 deletions

View File

@ -1724,17 +1724,10 @@ Description of some debug flags:
** gnupg.org notations
- adsk@gnupg.org :: Additional decryption subkey. This notation
gives a list of keys an implementation SHOULD
also encrypt to. The data consists of an array
of eight-octet numbers holding the Key ID of an
encryption subkey. This notation is only valid
on an encryption subkey (i.e. with first octet
of the key flags 0x04 or 0x08). Subkeys not on
the same keyblock MUST NOT be considered. For
interoperability this notation SHOULD NOT be
marked as criticial. Due to its nature it MUST
NOT be marked as human readable.
- rem@gnupg.org :: Used by Kleopatra to implement the tag feature.
These tags are used to mark keys for easier
searching and grouping.
** Simplified revocation certificates
Revocation certificates consist only of the signature packet;

View File

@ -1067,6 +1067,15 @@ signing.
"sensitive". If a designated revoker is marked as sensitive, it will
not be exported by default (see export-options).
@item addadsk
@opindex keyedit:addadsk
Add an Additional Decryption Subkey. The user is asked to enter the
fingerprint of another encryption subkey. Note that the exact
fingerprint of another key's encryption subkey needs to be entered.
This is because commonly the primary key has no encryption
capability. Use the option @option{--with-subkey-fingerprint} with
a list command to display the subkey fingerprints.
@item passwd
@opindex keyedit:passwd
Change the passphrase of the secret key.

View File

@ -1345,19 +1345,23 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type,
/*
* Put all the required stuff from SIG into subpackets of sig.
* PKSK is the signing key.
* PKSK is the signing key. SIGNHINTS are various flags like
* SIGNHINT_ADSK.
* Hmmm, should we delete those subpackets which are in a wrong area?
*/
void
build_sig_subpkt_from_sig (PKT_signature *sig, PKT_public_key *pksk)
build_sig_subpkt_from_sig (PKT_signature *sig, PKT_public_key *pksk,
unsigned int signhints)
{
u32 u;
byte buf[1+MAX_FINGERPRINT_LEN];
size_t fprlen;
/* For v4 keys we need to write the ISSUER subpacket. We do not
* want that for a future v5 format. */
if (pksk->version < 5)
* want that for a future v5 format. We also don't write it if
* only the new RENC keyflag is set (implementations with support
* for this key flag should understand the ISSUER_FPR). */
if (pksk->version < 5 && !(signhints & SIGNHINT_ADSK))
{
u = sig->keyid[0];
buf[0] = (u >> 24) & 0xff;

View File

@ -211,10 +211,10 @@ copy_prefs (const prefitem_t *prefs)
/* Copy the public key S to D. If D is NULL allocate a new public key
structure. If S has seckret key infos, only the public stuff is
copied. */
* structure. Only the basic stuff is copied; not any ancillary
* data. */
PKT_public_key *
copy_public_key (PKT_public_key *d, PKT_public_key *s)
copy_public_key_basics (PKT_public_key *d, PKT_public_key *s)
{
int n, i;
@ -222,8 +222,8 @@ copy_public_key (PKT_public_key *d, PKT_public_key *s)
d = xmalloc (sizeof *d);
memcpy (d, s, sizeof *d);
d->seckey_info = NULL;
d->user_id = scopy_user_id (s->user_id);
d->prefs = copy_prefs (s->prefs);
d->user_id = NULL;
d->prefs = NULL;
n = pubkey_get_npkey (s->pubkey_algo);
i = 0;
@ -237,6 +237,24 @@ copy_public_key (PKT_public_key *d, PKT_public_key *s)
for (; i < PUBKEY_MAX_NSKEY; i++)
d->pkey[i] = NULL;
d->revkey = NULL;
d->serialno = NULL;
d->updateurl = NULL;
return d;
}
/* Copy the public key S to D. If D is NULL allocate a new public key
structure. If S has seckret key infos, only the public stuff is
copied. */
PKT_public_key *
copy_public_key (PKT_public_key *d, PKT_public_key *s)
{
d = copy_public_key_basics (d, s);
d->user_id = scopy_user_id (s->user_id);
d->prefs = copy_prefs (s->prefs);
if (!s->revkey && s->numrevkeys)
BUG();
if (s->numrevkeys)
@ -244,8 +262,6 @@ copy_public_key (PKT_public_key *d, PKT_public_key *s)
d->revkey = xmalloc(sizeof(struct revocation_key)*s->numrevkeys);
memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys);
}
else
d->revkey = NULL;
if (s->serialno)
d->serialno = xstrdup (s->serialno);

View File

@ -1809,12 +1809,12 @@ get_pubkey_from_buffer (ctrl_t ctrl, PKT_public_key *pkbuf,
* returned public key may be a subkey rather than the primary key.
* Note: The self-signed data has already been merged into the public
* key using merge_selfsigs. Free *PK by calling
* release_public_key_parts (or, if PK was allocated using xfree, you
* release_public_key_parts (or, if PK was allocated using xmalloc, you
* can use free_public_key, which calls release_public_key_parts(PK)
* and then xfree(PK)).
*
* If PK->REQ_USAGE is set, it is used to filter the search results.
* (Thus, if PK is not NULL, PK->REQ_USAGE must be valid!!!) See the
* Thus, if PK is not NULL, PK->REQ_USAGE must be valid! See the
* documentation for finish_lookup to understand exactly how this is
* used.
*
@ -2417,7 +2417,8 @@ merge_keys_and_selfsig (ctrl_t ctrl, kbnode_t keyblock)
}
static int
/* This function parses the key flags and returns PUBKEY_USAGE_ flags. */
unsigned int
parse_key_usage (PKT_signature * sig)
{
int key_usage = 0;

View File

@ -468,6 +468,9 @@ void setup_main_keyids (kbnode_t keyblock);
data structures. */
void merge_keys_and_selfsig (ctrl_t ctrl, kbnode_t keyblock);
/* This function parses the key flags and returns PUBKEY_USAGE_ flags. */
unsigned int parse_key_usage (PKT_signature *sig);
char *get_user_id_string_native (ctrl_t ctrl, u32 *keyid);
char *get_long_user_id_string (ctrl_t ctrl, u32 *keyid);
char *get_user_id (ctrl_t ctrl, u32 *keyid, size_t *rn, int *r_nouid);

View File

@ -1,7 +1,7 @@
/* keyedit.c - Edit properties of a key
* Copyright (C) 1998-2010 Free Software Foundation, Inc.
* Copyright (C) 1998-2017 Werner Koch
* Copyright (C) 2015, 2016, 2022 g10 Code GmbH
* Copyright (C) 2015, 2016, 2022-2023 g10 Code GmbH
*
* This file is part of GnuPG.
*
@ -73,6 +73,7 @@ static int menu_delsig (ctrl_t ctrl, kbnode_t pub_keyblock);
static int menu_clean (ctrl_t ctrl, kbnode_t keyblock, int self_only);
static void menu_delkey (KBNODE pub_keyblock);
static int menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive);
static int menu_addadsk (ctrl_t ctrl, kbnode_t pub_keyblock);
static gpg_error_t menu_expire (ctrl_t ctrl, kbnode_t pub_keyblock,
int unattended, u32 newexpiration);
static int menu_changeusage (ctrl_t ctrl, kbnode_t keyblock);
@ -1243,7 +1244,7 @@ enum cmdids
cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG,
cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY,
cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
cmdEXPIRE, cmdCHANGEUSAGE, cmdBACKSIGN,
cmdEXPIRE, cmdCHANGEUSAGE, cmdBACKSIGN, cmdADDADSK,
#ifndef NO_TRUST_MODELS
cmdENABLEKEY, cmdDISABLEKEY,
#endif /*!NO_TRUST_MODELS*/
@ -1308,6 +1309,8 @@ static struct
{ "delkey", cmdDELKEY, 0, N_("delete selected subkeys")},
{ "addrevoker", cmdADDREVOKER, KEYEDIT_NEED_SK,
N_("add a revocation key")},
{ "addadsk", cmdADDADSK, KEYEDIT_NEED_SK,
N_("add additional decryption subkeys")},
{ "delsig", cmdDELSIG, 0,
N_("delete signatures from the selected user IDs")},
{ "expire", cmdEXPIRE, KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK,
@ -2000,6 +2003,15 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
}
break;
case cmdADDADSK:
if (menu_addadsk (ctrl, keyblock))
{
redisplay = 1;
modified = 1;
merge_keys_and_selfsig (ctrl, keyblock);
}
break;
case cmdREVUID:
{
int n1;
@ -4643,6 +4655,159 @@ fail:
}
/*
* Ask for a new additional decryption subkey and add it to the key
* block. Returns true if the keybloxk was changed and false
* otherwise.
*/
static int
menu_addadsk (ctrl_t ctrl, kbnode_t pub_keyblock)
{
PKT_public_key *pk;
PKT_public_key *sub_pk;
PKT_public_key *main_pk;
PKT_public_key *adsk_pk = NULL;
kbnode_t adsk_keyblock = NULL;
PKT_signature *sig = NULL;
char *answer = NULL;
gpg_error_t err;
KEYDB_SEARCH_DESC desc;
byte fpr[MAX_FINGERPRINT_LEN];
size_t fprlen;
kbnode_t node, node2;
kbnode_t subkeynode = NULL;
PACKET *pkt; /* (temp. use; will be put into a kbnode_t) */
log_assert (pub_keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
main_pk = pub_keyblock->pkt->pkt.public_key;
for (;;)
{
xfree (answer);
answer = cpr_get_utf8
("keyedit.addadsk",
_("Enter the fingerprint of the additional decryption subkey: "));
if (answer[0] == '\0' || answer[0] == CONTROL_D)
{
err = gpg_error (GPG_ERR_CANCELED);
goto leave;
}
if (classify_user_id (answer, &desc, 1)
|| desc.mode != KEYDB_SEARCH_MODE_FPR)
{
log_info (_("\"%s\" is not a fingerprint\n"), answer);
continue;
}
free_public_key (adsk_pk);
adsk_pk = xcalloc (1, sizeof *adsk_pk);
adsk_pk->req_usage = PUBKEY_USAGE_ENC;
release_kbnode (adsk_keyblock);
adsk_keyblock = NULL;
err = get_pubkey_byname (ctrl, GET_PUBKEY_NO_AKL,
NULL, adsk_pk, answer, &adsk_keyblock, NULL, 1);
if (err)
{
log_info (_("key \"%s\" not found: %s\n"), answer,
gpg_strerror (err));
if (!opt.batch && gpg_err_code (err) == GPG_ERR_UNUSABLE_PUBKEY)
log_info (_("Did you specify the fingerprint of a subkey?\n"));
continue;
}
for (node = adsk_keyblock; node; node = node->next)
{
if (node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
pk = node->pkt->pkt.public_key;
fingerprint_from_pk (pk, fpr, &fprlen);
if (fprlen == desc.fprlen
&& !memcmp (fpr, desc.u.fpr, fprlen)
&& (pk->pubkey_usage & PUBKEY_USAGE_ENC))
break;
}
}
if (!node)
{
err = gpg_error (GPG_ERR_WRONG_KEY_USAGE);
log_info (_("key \"%s\" not found: %s\n"), answer,
gpg_strerror (err));
if (!opt.batch)
log_info (_("Did you specify the fingerprint of a subkey?\n"));
continue;
}
/* Check that the selected subkey is not yet on our keyblock. */
for (node2 = pub_keyblock; node2; node2 = node2->next)
{
if (node2->pkt->pkttype == PKT_PUBLIC_KEY
|| node2->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
pk = node2->pkt->pkt.public_key;
fingerprint_from_pk (pk, fpr, &fprlen);
if (fprlen == desc.fprlen
&& !memcmp (fpr, desc.u.fpr, fprlen))
break;
}
}
if (node2)
{
log_info (_("key \"%s\" is already on this keyblock\n"), answer);
continue;
}
break;
}
/* Append the subkey.
* Note that we don't use the ADSK_PK directly because this is the
* primary key and in general we use a subkey to which NODE points.
* ADSK_PK has only been used to pass the requested key usage to
* get_pubkey_byname. SUB_PK will point to the actual adsk. */
log_assert (node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY);
sub_pk = copy_public_key_basics (NULL, node->pkt->pkt.public_key);
keyid_from_pk (main_pk, sub_pk->main_keyid); /* Fixup main keyid. */
log_assert ((sub_pk->pubkey_usage & PUBKEY_USAGE_ENC));
sub_pk->pubkey_usage = PUBKEY_USAGE_RENC; /* 'e' -> 'r' */
pkt = xcalloc (1, sizeof *pkt);
pkt->pkttype = PKT_PUBLIC_SUBKEY; /* Make sure it is a subkey. */
pkt->pkt.public_key = sub_pk;
subkeynode = new_kbnode (pkt);
/* Make the signature. */
err = make_keysig_packet (ctrl, &sig, main_pk, NULL, sub_pk, main_pk, 0x18,
sub_pk->timestamp, 0,
keygen_add_key_flags_and_expire, sub_pk, NULL);
if (err)
{
write_status_error ("keysig", err);
log_error ("creating key binding failed: %s\n", gpg_strerror (err));
goto leave;
}
/* Append the subkey packet and the binding signature. */
add_kbnode (pub_keyblock, subkeynode);
subkeynode = NULL;
pkt = xcalloc (1, sizeof *pkt);
pkt->pkttype = PKT_SIGNATURE;
pkt->pkt.signature = sig;
add_kbnode (pub_keyblock, new_kbnode (pkt));
leave:
xfree (answer);
free_public_key (adsk_pk);
release_kbnode (adsk_keyblock);
release_kbnode (subkeynode);
if (!err)
return 1; /* The keyblock was modified. */
else
return 0; /* Not modified. */
}
/* With FORCE_MAINKEY cleared this function handles the interactive
* menu option "expire". With UNATTENDED set to 1 this function only
* sets the expiration date of the primary key to NEWEXPIRATION and

View File

@ -130,12 +130,6 @@ struct output_control_s
};
struct opaque_data_usage_and_pk {
unsigned int usage;
PKT_public_key *pk;
};
/* FIXME: These globals vars are ugly. And using MAX_PREFS even for
* aeads is useless, given that we don't expects more than a very few
* algorithms. */
@ -256,22 +250,27 @@ write_uid (kbnode_t root, const char *s)
static void
do_add_key_flags (PKT_signature *sig, unsigned int use)
{
byte buf[1];
byte buf[2] = { 0, 0 };
buf[0] = 0;
/* The spec says that all primary keys MUST be able to certify. */
if ( sig->sig_class != 0x18 )
buf[0] |= 0x01;
/* The spec says that all primary keys MUST be able to certify. */
if(sig->sig_class!=0x18)
buf[0] |= 0x01;
if (use & PUBKEY_USAGE_SIG)
buf[0] |= 0x02;
if (use & PUBKEY_USAGE_ENC)
buf[0] |= 0x04 | 0x08;
if (use & PUBKEY_USAGE_AUTH)
buf[0] |= 0x20;
if (use & PUBKEY_USAGE_GROUP)
buf[0] |= 0x80;
if (use & PUBKEY_USAGE_SIG)
buf[0] |= 0x02;
if (use & PUBKEY_USAGE_ENC)
buf[0] |= 0x04 | 0x08;
if (use & PUBKEY_USAGE_AUTH)
buf[0] |= 0x20;
if (use & PUBKEY_USAGE_RENC)
buf[1] |= 0x04;
if (use & PUBKEY_USAGE_TIME)
buf[1] |= 0x08;
build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1);
build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, buf[1]? 2:1);
}
@ -318,13 +317,11 @@ keygen_add_key_flags (PKT_signature *sig, void *opaque)
}
static int
int
keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque)
{
struct opaque_data_usage_and_pk *oduap = opaque;
do_add_key_flags (sig, oduap->usage);
return keygen_add_key_expire (sig, oduap->pk);
keygen_add_key_flags (sig, opaque);
return keygen_add_key_expire (sig, opaque);
}
@ -1215,7 +1212,6 @@ write_keybinding (ctrl_t ctrl, kbnode_t root,
PKT_signature *sig;
KBNODE node;
PKT_public_key *pri_pk, *sub_pk;
struct opaque_data_usage_and_pk oduap;
if (opt.verbose)
log_info(_("writing key binding signature\n"));
@ -1241,11 +1237,10 @@ write_keybinding (ctrl_t ctrl, kbnode_t root,
BUG();
/* Make the signature. */
oduap.usage = use;
oduap.pk = sub_pk;
sub_pk->pubkey_usage = use;
err = make_keysig_packet (ctrl, &sig, pri_pk, NULL, sub_pk, pri_psk, 0x18,
timestamp, 0,
keygen_add_key_flags_and_expire, &oduap,
keygen_add_key_flags_and_expire, sub_pk,
cache_nonce);
if (err)
{

View File

@ -315,6 +315,7 @@ int keygen_set_std_prefs (const char *string,int personal);
PKT_user_id *keygen_get_std_prefs (void);
int keygen_add_key_expire( PKT_signature *sig, void *opaque );
int keygen_add_key_flags (PKT_signature *sig, void *opaque);
int keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque);
int keygen_add_std_prefs( PKT_signature *sig, void *opaque );
int keygen_upd_std_prefs( PKT_signature *sig, void *opaque );
int keygen_add_keyserver_url(PKT_signature *sig, void *opaque);

View File

@ -777,21 +777,21 @@ openpgp_pk_algo_usage ( int algo )
switch ( algo ) {
case PUBKEY_ALGO_RSA:
use = (PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG
| PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH);
| PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC | PUBKEY_USAGE_AUTH);
break;
case PUBKEY_ALGO_RSA_E:
case PUBKEY_ALGO_ECDH:
use = PUBKEY_USAGE_ENC;
use = PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC;
break;
case PUBKEY_ALGO_RSA_S:
use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG;
break;
case PUBKEY_ALGO_ELGAMAL:
if (RFC2440)
use = PUBKEY_USAGE_ENC;
use = PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC;
break;
case PUBKEY_ALGO_ELGAMAL_E:
use = PUBKEY_USAGE_ENC;
use = PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC;
break;
case PUBKEY_ALGO_DSA:
use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH;

View File

@ -56,9 +56,15 @@
| GCRY_PK_USAGE_AUTH | GCRY_PK_USAGE_UNKN) >= 256
# error Please choose another value for PUBKEY_USAGE_NONE
#endif
#define PUBKEY_USAGE_RENC 512 /* Restricted encryption. */
#define PUBKEY_USAGE_TIME 1024 /* Timestamp use. */
#define PUBKEY_USAGE_GROUP 512 /* Group flag. */
#define PUBKEY_USAGE_RENC 1024 /* Restricted encryption. */
#define PUBKEY_USAGE_TIME 2048 /* Timestamp use. */
/* Bitflags to convey hints on what kind of signature is created. */
#define SIGNHINT_KEYSIG 1
#define SIGNHINT_SELFSIG 2
#define SIGNHINT_ADSK 4
/* Helper macros. */
#define is_RSA(a) ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \
@ -287,7 +293,7 @@ typedef struct
/* The length of ATTRIB_DATA. */
unsigned long attrib_len;
byte *namehash;
int help_key_usage;
u16 help_key_usage;
u32 help_key_expire;
int help_full_count;
int help_marginal_count;
@ -388,7 +394,7 @@ typedef struct
byte selfsigversion; /* highest version of all of the self-sigs */
/* The public key algorithm. (Serialized.) */
byte pubkey_algo;
byte pubkey_usage; /* for now only used to pass it to getkey() */
u16 pubkey_usage; /* carries the usage info. */
byte req_usage; /* hack to pass a request to getkey() */
byte fprlen; /* 0 or length of FPR. */
u32 has_expired; /* set to the expiration date if expired */
@ -861,7 +867,8 @@ gpg_error_t gpg_mpi_write_nohdr (iobuf_t out, gcry_mpi_t a);
u32 calc_packet_length( PACKET *pkt );
void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
const byte *buffer, size_t buflen );
void build_sig_subpkt_from_sig (PKT_signature *sig, PKT_public_key *pksk);
void build_sig_subpkt_from_sig (PKT_signature *sig, PKT_public_key *pksk,
unsigned int signhints);
int delete_sig_subpkt(subpktarea_t *buffer, sigsubpkttype_t type );
void build_attribute_subpkt(PKT_user_id *uid,byte type,
const void *buf,u32 buflen,
@ -883,6 +890,7 @@ void free_user_id( PKT_user_id *uid );
void free_comment( PKT_comment *rem );
void free_packet (PACKET *pkt, parse_packet_ctx_t parsectx);
prefitem_t *copy_prefs (const prefitem_t *prefs);
PKT_public_key *copy_public_key_basics (PKT_public_key *d, PKT_public_key *s);
PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s );
PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s );
PKT_user_id *scopy_user_id (PKT_user_id *sd );

View File

@ -363,7 +363,8 @@ check_signature_metadata_validity (PKT_public_key *pk, PKT_signature *sig,
if (r_revoked)
*r_revoked = 0;
if (pk->timestamp > sig->timestamp )
if (pk->timestamp > sig->timestamp
&& !(parse_key_usage (sig) & PUBKEY_USAGE_RENC))
{
ulong d = pk->timestamp - sig->timestamp;
if ( d < 86400 )

View File

@ -50,11 +50,6 @@
#endif
/* Bitflags to convey hints on what kind of signayire is created. */
#define SIGNHINT_KEYSIG 1
#define SIGNHINT_SELFSIG 2
/* Hack */
static int recipient_digest_algo;
@ -416,7 +411,10 @@ do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig,
byte *dp;
char *hexgrip;
if (pksk->timestamp > sig->timestamp )
/* An ADSK key commonly has a creation date older than the primary
* key. For example because the ADSK is used as an archive key for
* a group of users. */
if (pksk->timestamp > sig->timestamp && !(signhints & SIGNHINT_ADSK))
{
ulong d = pksk->timestamp - sig->timestamp;
log_info (ngettext("key %s was created %lu second"
@ -964,7 +962,7 @@ write_signature_packets (ctrl_t ctrl,
if (gcry_md_copy (&md, hash))
BUG ();
build_sig_subpkt_from_sig (sig, pk);
build_sig_subpkt_from_sig (sig, pk, 0);
mk_notation_policy_etc (ctrl, sig, NULL, pk);
if (opt.flags.include_key_block && IS_SIG (sig))
err = mk_sig_subpkt_key_block (ctrl, sig, pk);
@ -1758,14 +1756,14 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
*
* SIGCLASS is the type of signature to create.
*
* DIGEST_ALGO is the digest algorithm. If it is 0 the function
* selects an appropriate one.
*
* TIMESTAMP is the timestamp to use for the signature. 0 means "now"
*
* DURATION is the amount of time (in seconds) until the signature
* expires.
*
* If CACHED_NONCE is not NULL the agent may use it to avoid
* additional pinnetry popups for the same keyblock.
*
* This function creates the following subpackets: issuer, created,
* and expire (if duration is not 0). Additional subpackets can be
* added using MKSUBPKT, which is called after these subpackets are
@ -1833,6 +1831,8 @@ make_keysig_packet (ctrl_t ctrl,
{
/* Hash the subkey binding/backsig/revocation. */
hash_public_key (md, subpk);
if ((subpk->pubkey_usage & PUBKEY_USAGE_RENC))
signhints |= SIGNHINT_ADSK;
}
else if (sigclass != 0x1F && sigclass != 0x20)
{
@ -1852,7 +1852,7 @@ make_keysig_packet (ctrl_t ctrl,
sig->expiredate = sig->timestamp + duration;
sig->sig_class = sigclass;
build_sig_subpkt_from_sig (sig, pksk);
build_sig_subpkt_from_sig (sig, pksk, signhints);
mk_notation_policy_etc (ctrl, sig, pk, pksk);
/* Crucial that the call to mksubpkt comes LAST before the calls
@ -1976,6 +1976,12 @@ update_keysig_packet (ctrl_t ctrl,
}
}
/* Detect an ADSK key binding signature. */
if ((sig->sig_class == 0x18
|| sig->sig_class == 0x19 || sig->sig_class == 0x28)
&& (pk->pubkey_usage & PUBKEY_USAGE_RENC))
signhints |= SIGNHINT_ADSK;
/* Note that already expired sigs will remain expired (with a
* duration of 1) since build-packet.c:build_sig_subpkt_from_sig
* detects this case. */
@ -1984,7 +1990,7 @@ update_keysig_packet (ctrl_t ctrl,
* automagically lower any sig expiration dates to correctly
* correspond to the differences in the timestamps (i.e. the
* duration will shrink). */
build_sig_subpkt_from_sig (sig, pksk);
build_sig_subpkt_from_sig (sig, pksk, signhints);
if (mksubpkt)
rc = (*mksubpkt)(sig, opaque);