mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
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:
parent
1aaadede76
commit
3a18378a92
15
doc/DETAILS
15
doc/DETAILS
@ -1724,17 +1724,10 @@ Description of some debug flags:
|
|||||||
|
|
||||||
** gnupg.org notations
|
** gnupg.org notations
|
||||||
|
|
||||||
- adsk@gnupg.org :: Additional decryption subkey. This notation
|
- rem@gnupg.org :: Used by Kleopatra to implement the tag feature.
|
||||||
gives a list of keys an implementation SHOULD
|
These tags are used to mark keys for easier
|
||||||
also encrypt to. The data consists of an array
|
searching and grouping.
|
||||||
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.
|
|
||||||
|
|
||||||
** Simplified revocation certificates
|
** Simplified revocation certificates
|
||||||
Revocation certificates consist only of the signature packet;
|
Revocation certificates consist only of the signature packet;
|
||||||
|
@ -1067,6 +1067,15 @@ signing.
|
|||||||
"sensitive". If a designated revoker is marked as sensitive, it will
|
"sensitive". If a designated revoker is marked as sensitive, it will
|
||||||
not be exported by default (see export-options).
|
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
|
@item passwd
|
||||||
@opindex keyedit:passwd
|
@opindex keyedit:passwd
|
||||||
Change the passphrase of the secret key.
|
Change the passphrase of the secret key.
|
||||||
|
@ -1345,19 +1345,23 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Put all the required stuff from SIG into subpackets of sig.
|
* 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?
|
* Hmmm, should we delete those subpackets which are in a wrong area?
|
||||||
*/
|
*/
|
||||||
void
|
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;
|
u32 u;
|
||||||
byte buf[1+MAX_FINGERPRINT_LEN];
|
byte buf[1+MAX_FINGERPRINT_LEN];
|
||||||
size_t fprlen;
|
size_t fprlen;
|
||||||
|
|
||||||
/* For v4 keys we need to write the ISSUER subpacket. We do not
|
/* For v4 keys we need to write the ISSUER subpacket. We do not
|
||||||
* want that for a future v5 format. */
|
* want that for a future v5 format. We also don't write it if
|
||||||
if (pksk->version < 5)
|
* 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];
|
u = sig->keyid[0];
|
||||||
buf[0] = (u >> 24) & 0xff;
|
buf[0] = (u >> 24) & 0xff;
|
||||||
|
@ -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
|
/* 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
|
* structure. Only the basic stuff is copied; not any ancillary
|
||||||
copied. */
|
* data. */
|
||||||
PKT_public_key *
|
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;
|
int n, i;
|
||||||
|
|
||||||
@ -222,8 +222,8 @@ copy_public_key (PKT_public_key *d, PKT_public_key *s)
|
|||||||
d = xmalloc (sizeof *d);
|
d = xmalloc (sizeof *d);
|
||||||
memcpy (d, s, sizeof *d);
|
memcpy (d, s, sizeof *d);
|
||||||
d->seckey_info = NULL;
|
d->seckey_info = NULL;
|
||||||
d->user_id = scopy_user_id (s->user_id);
|
d->user_id = NULL;
|
||||||
d->prefs = copy_prefs (s->prefs);
|
d->prefs = NULL;
|
||||||
|
|
||||||
n = pubkey_get_npkey (s->pubkey_algo);
|
n = pubkey_get_npkey (s->pubkey_algo);
|
||||||
i = 0;
|
i = 0;
|
||||||
@ -237,6 +237,24 @@ copy_public_key (PKT_public_key *d, PKT_public_key *s)
|
|||||||
for (; i < PUBKEY_MAX_NSKEY; i++)
|
for (; i < PUBKEY_MAX_NSKEY; i++)
|
||||||
d->pkey[i] = NULL;
|
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)
|
if (!s->revkey && s->numrevkeys)
|
||||||
BUG();
|
BUG();
|
||||||
if (s->numrevkeys)
|
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);
|
d->revkey = xmalloc(sizeof(struct revocation_key)*s->numrevkeys);
|
||||||
memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys);
|
memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
d->revkey = NULL;
|
|
||||||
|
|
||||||
if (s->serialno)
|
if (s->serialno)
|
||||||
d->serialno = xstrdup (s->serialno);
|
d->serialno = xstrdup (s->serialno);
|
||||||
|
@ -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.
|
* returned public key may be a subkey rather than the primary key.
|
||||||
* Note: The self-signed data has already been merged into the public
|
* Note: The self-signed data has already been merged into the public
|
||||||
* key using merge_selfsigs. Free *PK by calling
|
* 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)
|
* can use free_public_key, which calls release_public_key_parts(PK)
|
||||||
* and then xfree(PK)).
|
* and then xfree(PK)).
|
||||||
*
|
*
|
||||||
* If PK->REQ_USAGE is set, it is used to filter the search results.
|
* 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
|
* documentation for finish_lookup to understand exactly how this is
|
||||||
* used.
|
* 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)
|
parse_key_usage (PKT_signature * sig)
|
||||||
{
|
{
|
||||||
int key_usage = 0;
|
int key_usage = 0;
|
||||||
|
@ -468,6 +468,9 @@ void setup_main_keyids (kbnode_t keyblock);
|
|||||||
data structures. */
|
data structures. */
|
||||||
void merge_keys_and_selfsig (ctrl_t ctrl, kbnode_t keyblock);
|
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_user_id_string_native (ctrl_t ctrl, u32 *keyid);
|
||||||
char *get_long_user_id_string (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);
|
char *get_user_id (ctrl_t ctrl, u32 *keyid, size_t *rn, int *r_nouid);
|
||||||
|
169
g10/keyedit.c
169
g10/keyedit.c
@ -1,7 +1,7 @@
|
|||||||
/* keyedit.c - Edit properties of a key
|
/* keyedit.c - Edit properties of a key
|
||||||
* Copyright (C) 1998-2010 Free Software Foundation, Inc.
|
* Copyright (C) 1998-2010 Free Software Foundation, Inc.
|
||||||
* Copyright (C) 1998-2017 Werner Koch
|
* 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.
|
* 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 int menu_clean (ctrl_t ctrl, kbnode_t keyblock, int self_only);
|
||||||
static void menu_delkey (KBNODE pub_keyblock);
|
static void menu_delkey (KBNODE pub_keyblock);
|
||||||
static int menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive);
|
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,
|
static gpg_error_t menu_expire (ctrl_t ctrl, kbnode_t pub_keyblock,
|
||||||
int unattended, u32 newexpiration);
|
int unattended, u32 newexpiration);
|
||||||
static int menu_changeusage (ctrl_t ctrl, kbnode_t keyblock);
|
static int menu_changeusage (ctrl_t ctrl, kbnode_t keyblock);
|
||||||
@ -1243,7 +1244,7 @@ enum cmdids
|
|||||||
cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG,
|
cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG,
|
||||||
cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY,
|
cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY,
|
||||||
cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
|
cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
|
||||||
cmdEXPIRE, cmdCHANGEUSAGE, cmdBACKSIGN,
|
cmdEXPIRE, cmdCHANGEUSAGE, cmdBACKSIGN, cmdADDADSK,
|
||||||
#ifndef NO_TRUST_MODELS
|
#ifndef NO_TRUST_MODELS
|
||||||
cmdENABLEKEY, cmdDISABLEKEY,
|
cmdENABLEKEY, cmdDISABLEKEY,
|
||||||
#endif /*!NO_TRUST_MODELS*/
|
#endif /*!NO_TRUST_MODELS*/
|
||||||
@ -1308,6 +1309,8 @@ static struct
|
|||||||
{ "delkey", cmdDELKEY, 0, N_("delete selected subkeys")},
|
{ "delkey", cmdDELKEY, 0, N_("delete selected subkeys")},
|
||||||
{ "addrevoker", cmdADDREVOKER, KEYEDIT_NEED_SK,
|
{ "addrevoker", cmdADDREVOKER, KEYEDIT_NEED_SK,
|
||||||
N_("add a revocation key")},
|
N_("add a revocation key")},
|
||||||
|
{ "addadsk", cmdADDADSK, KEYEDIT_NEED_SK,
|
||||||
|
N_("add additional decryption subkeys")},
|
||||||
{ "delsig", cmdDELSIG, 0,
|
{ "delsig", cmdDELSIG, 0,
|
||||||
N_("delete signatures from the selected user IDs")},
|
N_("delete signatures from the selected user IDs")},
|
||||||
{ "expire", cmdEXPIRE, KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK,
|
{ "expire", cmdEXPIRE, KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK,
|
||||||
@ -2000,6 +2003,15 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case cmdADDADSK:
|
||||||
|
if (menu_addadsk (ctrl, keyblock))
|
||||||
|
{
|
||||||
|
redisplay = 1;
|
||||||
|
modified = 1;
|
||||||
|
merge_keys_and_selfsig (ctrl, keyblock);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case cmdREVUID:
|
case cmdREVUID:
|
||||||
{
|
{
|
||||||
int n1;
|
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
|
/* With FORCE_MAINKEY cleared this function handles the interactive
|
||||||
* menu option "expire". With UNATTENDED set to 1 this function only
|
* menu option "expire". With UNATTENDED set to 1 this function only
|
||||||
* sets the expiration date of the primary key to NEWEXPIRATION and
|
* sets the expiration date of the primary key to NEWEXPIRATION and
|
||||||
|
49
g10/keygen.c
49
g10/keygen.c
@ -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
|
/* 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
|
* aeads is useless, given that we don't expects more than a very few
|
||||||
* algorithms. */
|
* algorithms. */
|
||||||
@ -256,22 +250,27 @@ write_uid (kbnode_t root, const char *s)
|
|||||||
static void
|
static void
|
||||||
do_add_key_flags (PKT_signature *sig, unsigned int use)
|
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 (use & PUBKEY_USAGE_SIG)
|
||||||
if(sig->sig_class!=0x18)
|
buf[0] |= 0x02;
|
||||||
buf[0] |= 0x01;
|
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)
|
if (use & PUBKEY_USAGE_RENC)
|
||||||
buf[0] |= 0x02;
|
buf[1] |= 0x04;
|
||||||
if (use & PUBKEY_USAGE_ENC)
|
if (use & PUBKEY_USAGE_TIME)
|
||||||
buf[0] |= 0x04 | 0x08;
|
buf[1] |= 0x08;
|
||||||
if (use & PUBKEY_USAGE_AUTH)
|
|
||||||
buf[0] |= 0x20;
|
|
||||||
|
|
||||||
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)
|
keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque)
|
||||||
{
|
{
|
||||||
struct opaque_data_usage_and_pk *oduap = opaque;
|
keygen_add_key_flags (sig, opaque);
|
||||||
|
return keygen_add_key_expire (sig, opaque);
|
||||||
do_add_key_flags (sig, oduap->usage);
|
|
||||||
return keygen_add_key_expire (sig, oduap->pk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1215,7 +1212,6 @@ write_keybinding (ctrl_t ctrl, kbnode_t root,
|
|||||||
PKT_signature *sig;
|
PKT_signature *sig;
|
||||||
KBNODE node;
|
KBNODE node;
|
||||||
PKT_public_key *pri_pk, *sub_pk;
|
PKT_public_key *pri_pk, *sub_pk;
|
||||||
struct opaque_data_usage_and_pk oduap;
|
|
||||||
|
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
log_info(_("writing key binding signature\n"));
|
log_info(_("writing key binding signature\n"));
|
||||||
@ -1241,11 +1237,10 @@ write_keybinding (ctrl_t ctrl, kbnode_t root,
|
|||||||
BUG();
|
BUG();
|
||||||
|
|
||||||
/* Make the signature. */
|
/* Make the signature. */
|
||||||
oduap.usage = use;
|
sub_pk->pubkey_usage = use;
|
||||||
oduap.pk = sub_pk;
|
|
||||||
err = make_keysig_packet (ctrl, &sig, pri_pk, NULL, sub_pk, pri_psk, 0x18,
|
err = make_keysig_packet (ctrl, &sig, pri_pk, NULL, sub_pk, pri_psk, 0x18,
|
||||||
timestamp, 0,
|
timestamp, 0,
|
||||||
keygen_add_key_flags_and_expire, &oduap,
|
keygen_add_key_flags_and_expire, sub_pk,
|
||||||
cache_nonce);
|
cache_nonce);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
|
@ -315,6 +315,7 @@ int keygen_set_std_prefs (const char *string,int personal);
|
|||||||
PKT_user_id *keygen_get_std_prefs (void);
|
PKT_user_id *keygen_get_std_prefs (void);
|
||||||
int keygen_add_key_expire( PKT_signature *sig, void *opaque );
|
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 (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_add_std_prefs( PKT_signature *sig, void *opaque );
|
||||||
int keygen_upd_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);
|
int keygen_add_keyserver_url(PKT_signature *sig, void *opaque);
|
||||||
|
@ -777,21 +777,21 @@ openpgp_pk_algo_usage ( int algo )
|
|||||||
switch ( algo ) {
|
switch ( algo ) {
|
||||||
case PUBKEY_ALGO_RSA:
|
case PUBKEY_ALGO_RSA:
|
||||||
use = (PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG
|
use = (PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG
|
||||||
| PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH);
|
| PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC | PUBKEY_USAGE_AUTH);
|
||||||
break;
|
break;
|
||||||
case PUBKEY_ALGO_RSA_E:
|
case PUBKEY_ALGO_RSA_E:
|
||||||
case PUBKEY_ALGO_ECDH:
|
case PUBKEY_ALGO_ECDH:
|
||||||
use = PUBKEY_USAGE_ENC;
|
use = PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC;
|
||||||
break;
|
break;
|
||||||
case PUBKEY_ALGO_RSA_S:
|
case PUBKEY_ALGO_RSA_S:
|
||||||
use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG;
|
use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG;
|
||||||
break;
|
break;
|
||||||
case PUBKEY_ALGO_ELGAMAL:
|
case PUBKEY_ALGO_ELGAMAL:
|
||||||
if (RFC2440)
|
if (RFC2440)
|
||||||
use = PUBKEY_USAGE_ENC;
|
use = PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC;
|
||||||
break;
|
break;
|
||||||
case PUBKEY_ALGO_ELGAMAL_E:
|
case PUBKEY_ALGO_ELGAMAL_E:
|
||||||
use = PUBKEY_USAGE_ENC;
|
use = PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC;
|
||||||
break;
|
break;
|
||||||
case PUBKEY_ALGO_DSA:
|
case PUBKEY_ALGO_DSA:
|
||||||
use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH;
|
use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH;
|
||||||
|
18
g10/packet.h
18
g10/packet.h
@ -56,9 +56,15 @@
|
|||||||
| GCRY_PK_USAGE_AUTH | GCRY_PK_USAGE_UNKN) >= 256
|
| GCRY_PK_USAGE_AUTH | GCRY_PK_USAGE_UNKN) >= 256
|
||||||
# error Please choose another value for PUBKEY_USAGE_NONE
|
# error Please choose another value for PUBKEY_USAGE_NONE
|
||||||
#endif
|
#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_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. */
|
/* Helper macros. */
|
||||||
#define is_RSA(a) ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \
|
#define is_RSA(a) ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \
|
||||||
@ -287,7 +293,7 @@ typedef struct
|
|||||||
/* The length of ATTRIB_DATA. */
|
/* The length of ATTRIB_DATA. */
|
||||||
unsigned long attrib_len;
|
unsigned long attrib_len;
|
||||||
byte *namehash;
|
byte *namehash;
|
||||||
int help_key_usage;
|
u16 help_key_usage;
|
||||||
u32 help_key_expire;
|
u32 help_key_expire;
|
||||||
int help_full_count;
|
int help_full_count;
|
||||||
int help_marginal_count;
|
int help_marginal_count;
|
||||||
@ -388,7 +394,7 @@ typedef struct
|
|||||||
byte selfsigversion; /* highest version of all of the self-sigs */
|
byte selfsigversion; /* highest version of all of the self-sigs */
|
||||||
/* The public key algorithm. (Serialized.) */
|
/* The public key algorithm. (Serialized.) */
|
||||||
byte pubkey_algo;
|
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 req_usage; /* hack to pass a request to getkey() */
|
||||||
byte fprlen; /* 0 or length of FPR. */
|
byte fprlen; /* 0 or length of FPR. */
|
||||||
u32 has_expired; /* set to the expiration date if expired */
|
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 );
|
u32 calc_packet_length( PACKET *pkt );
|
||||||
void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
|
void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
|
||||||
const byte *buffer, size_t buflen );
|
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 );
|
int delete_sig_subpkt(subpktarea_t *buffer, sigsubpkttype_t type );
|
||||||
void build_attribute_subpkt(PKT_user_id *uid,byte type,
|
void build_attribute_subpkt(PKT_user_id *uid,byte type,
|
||||||
const void *buf,u32 buflen,
|
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_comment( PKT_comment *rem );
|
||||||
void free_packet (PACKET *pkt, parse_packet_ctx_t parsectx);
|
void free_packet (PACKET *pkt, parse_packet_ctx_t parsectx);
|
||||||
prefitem_t *copy_prefs (const prefitem_t *prefs);
|
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_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s );
|
||||||
PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s );
|
PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s );
|
||||||
PKT_user_id *scopy_user_id (PKT_user_id *sd );
|
PKT_user_id *scopy_user_id (PKT_user_id *sd );
|
||||||
|
@ -363,7 +363,8 @@ check_signature_metadata_validity (PKT_public_key *pk, PKT_signature *sig,
|
|||||||
if (r_revoked)
|
if (r_revoked)
|
||||||
*r_revoked = 0;
|
*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;
|
ulong d = pk->timestamp - sig->timestamp;
|
||||||
if ( d < 86400 )
|
if ( d < 86400 )
|
||||||
|
30
g10/sign.c
30
g10/sign.c
@ -50,11 +50,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Bitflags to convey hints on what kind of signayire is created. */
|
|
||||||
#define SIGNHINT_KEYSIG 1
|
|
||||||
#define SIGNHINT_SELFSIG 2
|
|
||||||
|
|
||||||
|
|
||||||
/* Hack */
|
/* Hack */
|
||||||
static int recipient_digest_algo;
|
static int recipient_digest_algo;
|
||||||
|
|
||||||
@ -416,7 +411,10 @@ do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig,
|
|||||||
byte *dp;
|
byte *dp;
|
||||||
char *hexgrip;
|
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;
|
ulong d = pksk->timestamp - sig->timestamp;
|
||||||
log_info (ngettext("key %s was created %lu second"
|
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))
|
if (gcry_md_copy (&md, hash))
|
||||||
BUG ();
|
BUG ();
|
||||||
|
|
||||||
build_sig_subpkt_from_sig (sig, pk);
|
build_sig_subpkt_from_sig (sig, pk, 0);
|
||||||
mk_notation_policy_etc (ctrl, sig, NULL, pk);
|
mk_notation_policy_etc (ctrl, sig, NULL, pk);
|
||||||
if (opt.flags.include_key_block && IS_SIG (sig))
|
if (opt.flags.include_key_block && IS_SIG (sig))
|
||||||
err = mk_sig_subpkt_key_block (ctrl, sig, pk);
|
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.
|
* 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"
|
* TIMESTAMP is the timestamp to use for the signature. 0 means "now"
|
||||||
*
|
*
|
||||||
* DURATION is the amount of time (in seconds) until the signature
|
* DURATION is the amount of time (in seconds) until the signature
|
||||||
* expires.
|
* 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,
|
* This function creates the following subpackets: issuer, created,
|
||||||
* and expire (if duration is not 0). Additional subpackets can be
|
* and expire (if duration is not 0). Additional subpackets can be
|
||||||
* added using MKSUBPKT, which is called after these subpackets are
|
* 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 the subkey binding/backsig/revocation. */
|
||||||
hash_public_key (md, subpk);
|
hash_public_key (md, subpk);
|
||||||
|
if ((subpk->pubkey_usage & PUBKEY_USAGE_RENC))
|
||||||
|
signhints |= SIGNHINT_ADSK;
|
||||||
}
|
}
|
||||||
else if (sigclass != 0x1F && sigclass != 0x20)
|
else if (sigclass != 0x1F && sigclass != 0x20)
|
||||||
{
|
{
|
||||||
@ -1852,7 +1852,7 @@ make_keysig_packet (ctrl_t ctrl,
|
|||||||
sig->expiredate = sig->timestamp + duration;
|
sig->expiredate = sig->timestamp + duration;
|
||||||
sig->sig_class = sigclass;
|
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);
|
mk_notation_policy_etc (ctrl, sig, pk, pksk);
|
||||||
|
|
||||||
/* Crucial that the call to mksubpkt comes LAST before the calls
|
/* 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
|
/* Note that already expired sigs will remain expired (with a
|
||||||
* duration of 1) since build-packet.c:build_sig_subpkt_from_sig
|
* duration of 1) since build-packet.c:build_sig_subpkt_from_sig
|
||||||
* detects this case. */
|
* detects this case. */
|
||||||
@ -1984,7 +1990,7 @@ update_keysig_packet (ctrl_t ctrl,
|
|||||||
* automagically lower any sig expiration dates to correctly
|
* automagically lower any sig expiration dates to correctly
|
||||||
* correspond to the differences in the timestamps (i.e. the
|
* correspond to the differences in the timestamps (i.e. the
|
||||||
* duration will shrink). */
|
* duration will shrink). */
|
||||||
build_sig_subpkt_from_sig (sig, pksk);
|
build_sig_subpkt_from_sig (sig, pksk, signhints);
|
||||||
|
|
||||||
if (mksubpkt)
|
if (mksubpkt)
|
||||||
rc = (*mksubpkt)(sig, opaque);
|
rc = (*mksubpkt)(sig, opaque);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user