mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-02 12:01:32 +01:00
gpg: New option --default-new-key-adsk and "addadsk" for edit-key.
* g10/free-packet.c (copy_public_key): Factor some code out to ... (copy_public_key_basics): new. * keygen.c (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. * g10/options.h (opt): Add field def_new_key_adsks. * g10/gpg.c (oDefaultNewKeyADSK): New. (opts): Add --default-new-key-adsk. (main): Parse option. * g10/keyedit.c (menu_addadsk): Factor some code out to ... (append_adsk_to_key): new. Add compliance check. * g10/keygen.c (pADSK): New. (para_data_s): Add adsk to the union. (release_parameter_list): Free the adsk. (prepare_adsk): New. (get_parameter_adsk): New. (get_parameter_revkey): Remove unneeded arg key and change callers. (proc_parameter_file): Prepare adsk parameter from the configured fingerprints. (do_generate_keypair): Create adsk. -- GnuPG-bug-id: 6882 (cherry picked from commit ed118e2ed521d82c1be7765a0a19d5b4f19afe10) and modified to adjust to other code changes
This commit is contained in:
parent
7eb39815bd
commit
eafe175320
25
doc/gpg.texi
25
doc/gpg.texi
@ -1729,13 +1729,26 @@ this option at all (e.g. due to the @option{--no-options} option).
|
|||||||
@opindex add-desig-revoker
|
@opindex add-desig-revoker
|
||||||
Add the key specified by @var{fingerprint} as a designated revoker to
|
Add the key specified by @var{fingerprint} as a designated revoker to
|
||||||
newly created keys. If the fingerprint is prefixed with the keyword
|
newly created keys. If the fingerprint is prefixed with the keyword
|
||||||
``sensitive:'' that info is normally not exported wit the key. This
|
``sensitive:'' that info is normally not exported with the key. This
|
||||||
option may be given several time to add more than one designated
|
option may be given several times to add more than one designated
|
||||||
revoker. If the keyword ``clear'' is used instead of a fingerprint,
|
revoker. If the keyword ``clear'' is used instead of a fingerprint,
|
||||||
all designated options previously encountered are discarded.
|
all previously given fingerprints are discarded. Designated revokers
|
||||||
Designated revokers are marked on the key as non-revocable. Note that
|
are marked on the key as non-revocable. Note that a designated
|
||||||
a designated revoker specified using a parameter file will also be
|
revoker specified using a parameter file will also be added to the
|
||||||
added to the key.
|
key.
|
||||||
|
|
||||||
|
@item --default-new-key-adsk @var{fingerprint}
|
||||||
|
@opindex default-new-key-adsk
|
||||||
|
Add the subkey specified by @var{fingerprint} as an Additional
|
||||||
|
Decryption Subkey (ADSK) to newly created keys. This option may be
|
||||||
|
given several time to add more than one ADSK. It is also possible to
|
||||||
|
give several fingerprints delimited by space or comma as value to this
|
||||||
|
option. If the keyword ``clear'' is used instead of a fingerprint,
|
||||||
|
all previously specified fingerprints are discarded (useful to
|
||||||
|
override options given in a config file). The fingerprint is expected
|
||||||
|
to specify a subkey and it does not need an exclamation mark as
|
||||||
|
suffix; it must be given in cmpact format (40 or 64 hex-digits without
|
||||||
|
any spaces).
|
||||||
|
|
||||||
|
|
||||||
@item --trust-model @{pgp|classic|tofu|tofu+pgp|direct|always|auto@}
|
@item --trust-model @{pgp|classic|tofu|tofu+pgp|direct|always|auto@}
|
||||||
|
@ -1123,19 +1123,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;
|
||||||
|
@ -189,10 +189,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;
|
||||||
|
|
||||||
@ -200,8 +200,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;
|
||||||
@ -215,6 +215,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)
|
||||||
|
13
g10/gpg.c
13
g10/gpg.c
@ -422,6 +422,7 @@ enum cmd_and_opt_values
|
|||||||
oTOFUDefaultPolicy,
|
oTOFUDefaultPolicy,
|
||||||
oTOFUDBFormat,
|
oTOFUDBFormat,
|
||||||
oDefaultNewKeyAlgo,
|
oDefaultNewKeyAlgo,
|
||||||
|
oDefaultNewKeyADSK,
|
||||||
oWeakDigest,
|
oWeakDigest,
|
||||||
oUnwrap,
|
oUnwrap,
|
||||||
oOnlySignTextIDs,
|
oOnlySignTextIDs,
|
||||||
@ -627,6 +628,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
ARGPARSE_s_n (oPGP7, "pgp7", "@"),
|
ARGPARSE_s_n (oPGP7, "pgp7", "@"),
|
||||||
ARGPARSE_s_n (oPGP8, "pgp8", "@"),
|
ARGPARSE_s_n (oPGP8, "pgp8", "@"),
|
||||||
ARGPARSE_s_s (oDefaultNewKeyAlgo, "default-new-key-algo", "@"),
|
ARGPARSE_s_s (oDefaultNewKeyAlgo, "default-new-key-algo", "@"),
|
||||||
|
ARGPARSE_s_s (oDefaultNewKeyADSK, "default-new-key-adsk", "@"),
|
||||||
ARGPARSE_p_u (oMinRSALength, "min-rsa-length", "@"),
|
ARGPARSE_p_u (oMinRSALength, "min-rsa-length", "@"),
|
||||||
#ifndef NO_TRUST_MODELS
|
#ifndef NO_TRUST_MODELS
|
||||||
ARGPARSE_s_n (oAlwaysTrust, "always-trust", "@"),
|
ARGPARSE_s_n (oAlwaysTrust, "always-trust", "@"),
|
||||||
@ -2309,6 +2311,7 @@ main (int argc, char **argv)
|
|||||||
const char *fname;
|
const char *fname;
|
||||||
char *username;
|
char *username;
|
||||||
int may_coredump;
|
int may_coredump;
|
||||||
|
gpg_error_t tmperr;
|
||||||
strlist_t sl;
|
strlist_t sl;
|
||||||
strlist_t remusr = NULL;
|
strlist_t remusr = NULL;
|
||||||
strlist_t locusr = NULL;
|
strlist_t locusr = NULL;
|
||||||
@ -3648,6 +3651,16 @@ main (int argc, char **argv)
|
|||||||
opt.def_new_key_algo = pargs.r.ret_str;
|
opt.def_new_key_algo = pargs.r.ret_str;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case oDefaultNewKeyADSK:
|
||||||
|
if (!strcmp (pargs.r.ret_str, "clear"))
|
||||||
|
FREE_STRLIST (opt.def_new_key_adsks);
|
||||||
|
else if (!tokenize_to_strlist (&opt.def_new_key_adsks,
|
||||||
|
pargs.r.ret_str, " \t,")
|
||||||
|
&& (tmperr = gpg_err_code_from_syserror()) != GPG_ERR_ENOENT)
|
||||||
|
log_info (_("error parsing value for option '%s': %s\n"),
|
||||||
|
"--default-new-key-algo", gpg_strerror (tmperr));
|
||||||
|
break;
|
||||||
|
|
||||||
case oUseOnlyOpenPGPCard:
|
case oUseOnlyOpenPGPCard:
|
||||||
opt.flags.use_only_openpgp_card = 1;
|
opt.flags.use_only_openpgp_card = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -3122,3 +3122,13 @@ keyedit_print_one_sig (ctrl_t ctrl, estream_t fp,
|
|||||||
(void) extended;
|
(void) extended;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gpg_error_t
|
||||||
|
append_adsk_to_key (ctrl_t ctrl, kbnode_t keyblock, PKT_public_key *adsk)
|
||||||
|
{
|
||||||
|
(void)ctrl;
|
||||||
|
(void)keyblock;
|
||||||
|
(void)adsk;
|
||||||
|
return GPG_ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
237
g10/keyedit.c
237
g10/keyedit.c
@ -73,6 +73,8 @@ 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,
|
||||||
|
const char *adskfpr);
|
||||||
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);
|
||||||
@ -1240,7 +1242,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*/
|
||||||
@ -1303,6 +1305,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,
|
||||||
@ -1966,6 +1970,15 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case cmdADDADSK:
|
||||||
|
if (menu_addadsk (ctrl, keyblock, NULL))
|
||||||
|
{
|
||||||
|
redisplay = 1;
|
||||||
|
modified = 1;
|
||||||
|
merge_keys_and_selfsig (ctrl, keyblock);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case cmdREVUID:
|
case cmdREVUID:
|
||||||
{
|
{
|
||||||
int n1;
|
int n1;
|
||||||
@ -4639,6 +4652,228 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Core function to add an ADSK to the KEYBLOCK. Returns 0 on success
|
||||||
|
* or an error code. */
|
||||||
|
gpg_error_t
|
||||||
|
append_adsk_to_key (ctrl_t ctrl, kbnode_t keyblock, PKT_public_key *adsk)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
PKT_public_key *main_pk; /* The primary key. */
|
||||||
|
PKT_signature *sig = NULL;
|
||||||
|
kbnode_t adsknode = NULL;
|
||||||
|
PACKET *pkt; /* (temp. use; will be put into a kbnode_t) */
|
||||||
|
|
||||||
|
/* First get a copy. */
|
||||||
|
adsk = copy_public_key_basics (NULL, adsk);
|
||||||
|
|
||||||
|
/* Check compliance. */
|
||||||
|
if (!gnupg_pk_is_compliant (opt.compliance, adsk->pubkey_algo, 0,
|
||||||
|
adsk->pkey, nbits_from_pk (adsk), NULL))
|
||||||
|
{
|
||||||
|
char pkhex[MAX_FINGERPRINT_LEN*2+1];
|
||||||
|
|
||||||
|
hexfingerprint (adsk, pkhex, sizeof pkhex);
|
||||||
|
log_error (_("WARNING: key %s is not suitable for encryption"
|
||||||
|
" in %s mode\n"),
|
||||||
|
pkhex, gnupg_compliance_option_string (opt.compliance));
|
||||||
|
err = gpg_error (GPG_ERR_FORBIDDEN);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the primary key. */
|
||||||
|
log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
|
||||||
|
main_pk = keyblock->pkt->pkt.public_key;
|
||||||
|
|
||||||
|
/* Prepare and append the adsk. */
|
||||||
|
keyid_from_pk (main_pk, adsk->main_keyid); /* Fixup main keyid. */
|
||||||
|
log_assert ((adsk->pubkey_usage & PUBKEY_USAGE_ENC));
|
||||||
|
adsk->pubkey_usage = PUBKEY_USAGE_RENC; /* 'e' -> 'r' */
|
||||||
|
pkt = xtrycalloc (1, sizeof *pkt);
|
||||||
|
if (!pkt)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
pkt->pkttype = PKT_PUBLIC_SUBKEY; /* Make sure it is a subkey. */
|
||||||
|
pkt->pkt.public_key = adsk;
|
||||||
|
adsknode = new_kbnode (pkt);
|
||||||
|
|
||||||
|
/* Make the signature. */
|
||||||
|
err = make_keysig_packet (ctrl, &sig, main_pk, NULL, adsk, main_pk, 0x18, 0,
|
||||||
|
adsk->timestamp, 0,
|
||||||
|
keygen_add_key_flags_and_expire, adsk, NULL);
|
||||||
|
adsk = NULL; /* (owned by adsknode - avoid double free.) */
|
||||||
|
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 (keyblock, adsknode);
|
||||||
|
adsknode = NULL;
|
||||||
|
pkt = xtrycalloc (1, sizeof *pkt);
|
||||||
|
if (!pkt)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
pkt->pkttype = PKT_SIGNATURE;
|
||||||
|
pkt->pkt.signature = sig;
|
||||||
|
add_kbnode (keyblock, new_kbnode (pkt));
|
||||||
|
|
||||||
|
leave:
|
||||||
|
release_kbnode (adsknode);
|
||||||
|
free_public_key (adsk); /* Release our copy. */
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ask for a new additional decryption subkey and add it to the key
|
||||||
|
* block. Returns true if the keyblock was changed and false
|
||||||
|
* otherwise. If ADSKFPR is not NULL, this function has been called
|
||||||
|
* by quick_addadsk and gives the fingerprint of the to be added key.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
menu_addadsk (ctrl_t ctrl, kbnode_t pub_keyblock, const char *adskfpr)
|
||||||
|
{
|
||||||
|
PKT_public_key *pk;
|
||||||
|
PKT_public_key *adsk_pk = NULL;
|
||||||
|
kbnode_t adsk_keyblock = NULL;
|
||||||
|
char *answer = NULL;
|
||||||
|
gpg_error_t err;
|
||||||
|
KEYDB_SEARCH_DESC desc;
|
||||||
|
byte fpr[MAX_FINGERPRINT_LEN];
|
||||||
|
size_t fprlen;
|
||||||
|
kbnode_t node, node2;
|
||||||
|
|
||||||
|
log_assert (pub_keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
xfree (answer);
|
||||||
|
if (adskfpr)
|
||||||
|
answer = xstrdup (adskfpr);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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
|
||||||
|
|| desc.mode == KEYDB_SEARCH_MODE_FPR20))
|
||||||
|
{
|
||||||
|
log_info (_("\"%s\" is not a fingerprint\n"), answer);
|
||||||
|
err = gpg_error (GPG_ERR_INV_USER_ID);
|
||||||
|
if (adskfpr)
|
||||||
|
goto leave;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Force searching for that exact fingerprint and for any key
|
||||||
|
* which has a key with that fingerprint. */
|
||||||
|
if (!strchr (answer, '!'))
|
||||||
|
{
|
||||||
|
char *tmpstr = xstrconcat (answer, "!", NULL);
|
||||||
|
xfree (answer);
|
||||||
|
answer = tmpstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 || adskfpr) && !opt.quiet
|
||||||
|
&& gpg_err_code (err) == GPG_ERR_UNUSABLE_PUBKEY)
|
||||||
|
log_info (_("Did you specify the fingerprint of a subkey?\n"));
|
||||||
|
if (adskfpr)
|
||||||
|
goto leave;
|
||||||
|
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 == 20
|
||||||
|
&& !memcmp (fpr, desc.u.fpr, 20)
|
||||||
|
&& (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 || adskfpr) && !opt.quiet)
|
||||||
|
log_info (_("Did you specify the fingerprint of a subkey?\n"));
|
||||||
|
if (adskfpr)
|
||||||
|
goto leave;
|
||||||
|
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 == 20
|
||||||
|
&& !memcmp (fpr, desc.u.fpr, 20))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node2)
|
||||||
|
{
|
||||||
|
log_info (_("key \"%s\" is already on this keyblock\n"), answer);
|
||||||
|
err = gpg_error (GPG_ERR_DUP_KEY);
|
||||||
|
if (adskfpr)
|
||||||
|
goto leave;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append the subkey. */
|
||||||
|
log_assert (node->pkt->pkttype == PKT_PUBLIC_KEY
|
||||||
|
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY);
|
||||||
|
err = append_adsk_to_key (ctrl, pub_keyblock, node->pkt->pkt.public_key);
|
||||||
|
|
||||||
|
|
||||||
|
leave:
|
||||||
|
xfree (answer);
|
||||||
|
free_public_key (adsk_pk);
|
||||||
|
release_kbnode (adsk_keyblock);
|
||||||
|
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
|
||||||
|
@ -55,6 +55,8 @@ void keyedit_quick_set_expire (ctrl_t ctrl,
|
|||||||
void keyedit_quick_set_primary (ctrl_t ctrl, const char *username,
|
void keyedit_quick_set_primary (ctrl_t ctrl, const char *username,
|
||||||
const char *primaryuid);
|
const char *primaryuid);
|
||||||
void keyedit_quick_update_pref (ctrl_t ctrl, const char *username);
|
void keyedit_quick_update_pref (ctrl_t ctrl, const char *username);
|
||||||
|
gpg_error_t append_adsk_to_key (ctrl_t ctrl, kbnode_t keyblock,
|
||||||
|
PKT_public_key *adsk);
|
||||||
void show_basic_key_info (ctrl_t ctrl, kbnode_t keyblock, int print_sec);
|
void show_basic_key_info (ctrl_t ctrl, kbnode_t keyblock, int print_sec);
|
||||||
int keyedit_print_one_sig (ctrl_t ctrl, estream_t fp,
|
int keyedit_print_one_sig (ctrl_t ctrl, estream_t fp,
|
||||||
int rc, kbnode_t keyblock,
|
int rc, kbnode_t keyblock,
|
||||||
|
184
g10/keygen.c
184
g10/keygen.c
@ -91,6 +91,7 @@ enum para_name {
|
|||||||
pKEYSERVER,
|
pKEYSERVER,
|
||||||
pKEYGRIP,
|
pKEYGRIP,
|
||||||
pSUBKEYGRIP,
|
pSUBKEYGRIP,
|
||||||
|
pADSK /* this uses u.adsk */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct para_data_s {
|
struct para_data_s {
|
||||||
@ -102,6 +103,7 @@ struct para_data_s {
|
|||||||
u32 creation;
|
u32 creation;
|
||||||
unsigned int usage;
|
unsigned int usage;
|
||||||
struct revocation_key revkey;
|
struct revocation_key revkey;
|
||||||
|
PKT_public_key *adsk; /* used with key == pADSK */
|
||||||
char value[1];
|
char value[1];
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
@ -246,22 +248,26 @@ 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)
|
build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, buf[1]? 2:1);
|
||||||
buf[0] |= 0x20;
|
|
||||||
|
|
||||||
build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -308,10 +314,18 @@ keygen_add_key_flags (PKT_signature *sig, void *opaque)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque)
|
||||||
|
{
|
||||||
|
keygen_add_key_flags (sig, opaque);
|
||||||
|
return keygen_add_key_expire (sig, opaque);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This is only used to write the key binding signature. It is not
|
/* This is only used to write the key binding signature. It is not
|
||||||
* used for the primary key. */
|
* used for the primary key. */
|
||||||
static int
|
static int
|
||||||
keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque)
|
keygen_add_key_flags_from_oduap (PKT_signature *sig, void *opaque)
|
||||||
{
|
{
|
||||||
struct opaque_data_usage_and_pk *oduap = opaque;
|
struct opaque_data_usage_and_pk *oduap = opaque;
|
||||||
|
|
||||||
@ -1224,7 +1238,7 @@ write_keybinding (ctrl_t ctrl, kbnode_t root,
|
|||||||
oduap.pk = sub_pk;
|
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,
|
||||||
0, timestamp, 0,
|
0, timestamp, 0,
|
||||||
keygen_add_key_flags_and_expire, &oduap,
|
keygen_add_key_flags_from_oduap, &oduap,
|
||||||
cache_nonce);
|
cache_nonce);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@ -3693,6 +3707,9 @@ release_parameter_list (struct para_data_s *r)
|
|||||||
r2 = r->next;
|
r2 = r->next;
|
||||||
if (r->key == pPASSPHRASE && *r->u.value)
|
if (r->key == pPASSPHRASE && *r->u.value)
|
||||||
wipememory (r->u.value, strlen (r->u.value));
|
wipememory (r->u.value, strlen (r->u.value));
|
||||||
|
else if (r->key == pADSK)
|
||||||
|
free_public_key (r->u.adsk);
|
||||||
|
|
||||||
xfree (r);
|
xfree (r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3889,7 +3906,8 @@ prepare_desig_revoker (ctrl_t ctrl, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (classify_user_id (name, &desc, 1)
|
if (classify_user_id (name, &desc, 1)
|
||||||
|| desc.mode != KEYDB_SEARCH_MODE_FPR)
|
|| !(desc.mode == KEYDB_SEARCH_MODE_FPR
|
||||||
|
|| desc.mode == KEYDB_SEARCH_MODE_FPR20))
|
||||||
{
|
{
|
||||||
log_info (_("\"%s\" is not a fingerprint\n"), name);
|
log_info (_("\"%s\" is not a fingerprint\n"), name);
|
||||||
err = gpg_error (GPG_ERR_INV_NAME);
|
err = gpg_error (GPG_ERR_INV_NAME);
|
||||||
@ -3928,6 +3946,60 @@ prepare_desig_revoker (ctrl_t ctrl, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Parse asn ADSK specified by NAME, check that the public key exists
|
||||||
|
* and return a parameter with the adsk information. On error print a
|
||||||
|
* diagnostic and return NULL. */
|
||||||
|
static struct para_data_s *
|
||||||
|
prepare_adsk (ctrl_t ctrl, const char *name)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
char *namebuffer = NULL;
|
||||||
|
struct para_data_s *para = NULL;
|
||||||
|
KEYDB_SEARCH_DESC desc;
|
||||||
|
PKT_public_key *adsk_pk = NULL;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (classify_user_id (name, &desc, 1)
|
||||||
|
|| !(desc.mode == KEYDB_SEARCH_MODE_FPR
|
||||||
|
|| desc.mode == KEYDB_SEARCH_MODE_FPR20))
|
||||||
|
{
|
||||||
|
log_info (_("\"%s\" is not a fingerprint\n"), name);
|
||||||
|
err = gpg_error (GPG_ERR_INV_NAME);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Force searching for that exact fingerprint. */
|
||||||
|
if (!strchr (name, '!'))
|
||||||
|
{
|
||||||
|
namebuffer = xstrconcat (name, "!", NULL);
|
||||||
|
name = namebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
adsk_pk = xcalloc (1, sizeof *adsk_pk);
|
||||||
|
adsk_pk->req_usage = PUBKEY_USAGE_ENC;
|
||||||
|
err = get_pubkey_byname (ctrl, GET_PUBKEY_NO_AKL,
|
||||||
|
NULL, adsk_pk, name, NULL, NULL, 1);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
para = xcalloc (1, sizeof *para);
|
||||||
|
para->key = pADSK;
|
||||||
|
para->u.adsk = adsk_pk;
|
||||||
|
adsk_pk = NULL;
|
||||||
|
|
||||||
|
leave:
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
if (namebuffer && (p=strchr (namebuffer, '!')))
|
||||||
|
*p = 0; /* Strip the ! for the diagnostic. */
|
||||||
|
log_error ("invalid ADSK '%s' specified: %s\n", name, gpg_strerror (err));
|
||||||
|
}
|
||||||
|
free_public_key (adsk_pk);
|
||||||
|
xfree (namebuffer);
|
||||||
|
return para;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Parse a pREVOKER parameter into its dedicated parts. */
|
/* Parse a pREVOKER parameter into its dedicated parts. */
|
||||||
static int
|
static int
|
||||||
parse_revocation_key (const char *fname,
|
parse_revocation_key (const char *fname,
|
||||||
@ -4007,13 +4079,19 @@ get_parameter_uint( struct para_data_s *para, enum para_name key )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct revocation_key *
|
static struct revocation_key *
|
||||||
get_parameter_revkey (struct para_data_s *para, enum para_name key,
|
get_parameter_revkey (struct para_data_s *para, unsigned int idx)
|
||||||
unsigned int idx)
|
|
||||||
{
|
{
|
||||||
struct para_data_s *r = get_parameter_idx (para, key, idx);
|
struct para_data_s *r = get_parameter_idx (para, pREVOKER, idx);
|
||||||
return r? &r->u.revkey : NULL;
|
return r? &r->u.revkey : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PKT_public_key *
|
||||||
|
get_parameter_adsk (struct para_data_s *para, unsigned int idx)
|
||||||
|
{
|
||||||
|
struct para_data_s *r = get_parameter_idx (para, pADSK, idx);
|
||||||
|
return r? r->u.adsk : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
proc_parameter_file (ctrl_t ctrl, struct para_data_s *para, const char *fname,
|
proc_parameter_file (ctrl_t ctrl, struct para_data_s *para, const char *fname,
|
||||||
struct output_control_s *outctrl, int card )
|
struct output_control_s *outctrl, int card )
|
||||||
@ -4022,7 +4100,7 @@ proc_parameter_file (ctrl_t ctrl, struct para_data_s *para, const char *fname,
|
|||||||
const char *s1, *s2, *s3;
|
const char *s1, *s2, *s3;
|
||||||
size_t n;
|
size_t n;
|
||||||
char *p;
|
char *p;
|
||||||
strlist_t sl;
|
strlist_t sl, slr;
|
||||||
int is_default = 0;
|
int is_default = 0;
|
||||||
int have_user_id = 0;
|
int have_user_id = 0;
|
||||||
int err, algo;
|
int err, algo;
|
||||||
@ -4182,8 +4260,36 @@ proc_parameter_file (ctrl_t ctrl, struct para_data_s *para, const char *fname,
|
|||||||
append_to_parameter (para, r);
|
append_to_parameter (para, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check and append ADSKs from the config file. While doing this
|
||||||
|
* also check for duplicate specifications. In addition we remove
|
||||||
|
* an optional '!' suffix for easier comparing; the suffix is anyway
|
||||||
|
* re-added later. */
|
||||||
|
for (sl = opt.def_new_key_adsks; sl; sl = sl->next)
|
||||||
|
{
|
||||||
|
if (!*sl->d)
|
||||||
|
continue;
|
||||||
|
p = strchr (sl->d, '!');
|
||||||
|
if (p)
|
||||||
|
*p = 0;
|
||||||
|
for (slr = opt.def_new_key_adsks; slr != sl; slr = slr->next)
|
||||||
|
if (!ascii_strcasecmp (sl->d, slr->d))
|
||||||
|
{
|
||||||
|
*sl->d = 0; /* clear fpr to mark this as a duplicate. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!*sl->d)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Make KEYCREATIONDATE from Creation-Date. */
|
r = prepare_adsk (ctrl, sl->d);
|
||||||
|
if (!r)
|
||||||
|
return -1;
|
||||||
|
append_to_parameter (para, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make KEYCREATIONDATE from Creation-Date. We ignore this if the
|
||||||
|
* key has been taken from a card and a keycreationtime has already
|
||||||
|
* been set. This is so that we don't generate a key with a
|
||||||
|
* fingerprint different from the one stored on the OpenPGP card. */
|
||||||
r = get_parameter (para, pCREATIONDATE);
|
r = get_parameter (para, pCREATIONDATE);
|
||||||
if (r && *r->u.value)
|
if (r && *r->u.value)
|
||||||
{
|
{
|
||||||
@ -5243,6 +5349,7 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
|||||||
u32 expire;
|
u32 expire;
|
||||||
const char *key_from_hexgrip = NULL;
|
const char *key_from_hexgrip = NULL;
|
||||||
unsigned int idx;
|
unsigned int idx;
|
||||||
|
int any_adsk = 0;
|
||||||
|
|
||||||
if (outctrl->dryrun)
|
if (outctrl->dryrun)
|
||||||
{
|
{
|
||||||
@ -5345,11 +5452,11 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Write all signatures specifying designated revokers. */
|
/* Write all signatures specifying designated revokers. */
|
||||||
for (idx=0;
|
for (idx=0; !err && (revkey = get_parameter_revkey (para, idx)); idx++)
|
||||||
!err && (revkey = get_parameter_revkey (para, pREVOKER, idx));
|
{
|
||||||
idx++)
|
err = write_direct_sig (ctrl, pub_root, pri_psk,
|
||||||
err = write_direct_sig (ctrl, pub_root, pri_psk,
|
revkey, timestamp, cache_nonce);
|
||||||
revkey, timestamp, cache_nonce);
|
}
|
||||||
|
|
||||||
if (!err && (s = get_parameter_value (para, pUSERID)))
|
if (!err && (s = get_parameter_value (para, pUSERID)))
|
||||||
{
|
{
|
||||||
@ -5426,6 +5533,25 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
|||||||
did_sub = 1;
|
did_sub = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get rid of the first empty packet. */
|
||||||
|
if (!err)
|
||||||
|
commit_kbnode (&pub_root);
|
||||||
|
|
||||||
|
/* Add ADSKs if any are specified. */
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
PKT_public_key *adsk;
|
||||||
|
|
||||||
|
for (idx=0; (adsk = get_parameter_adsk (para, idx)); idx++)
|
||||||
|
{
|
||||||
|
err = append_adsk_to_key (ctrl, pub_root, adsk);
|
||||||
|
if (err)
|
||||||
|
break;
|
||||||
|
any_adsk++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!err && outctrl->use_files) /* Direct write to specified files. */
|
if (!err && outctrl->use_files) /* Direct write to specified files. */
|
||||||
{
|
{
|
||||||
err = write_keyblock (outctrl->pub.stream, pub_root);
|
err = write_keyblock (outctrl->pub.stream, pub_root);
|
||||||
@ -5482,9 +5608,6 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
|||||||
|
|
||||||
gen_standard_revoke (ctrl, pk, cache_nonce);
|
gen_standard_revoke (ctrl, pk, cache_nonce);
|
||||||
|
|
||||||
/* Get rid of the first empty packet. */
|
|
||||||
commit_kbnode (&pub_root);
|
|
||||||
|
|
||||||
if (!opt.batch)
|
if (!opt.batch)
|
||||||
{
|
{
|
||||||
tty_printf (_("public and secret key created and signed.\n") );
|
tty_printf (_("public and secret key created and signed.\n") );
|
||||||
@ -5526,6 +5649,9 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
|||||||
PKT_PUBLIC_KEY)->pkt->pkt.public_key;
|
PKT_PUBLIC_KEY)->pkt->pkt.public_key;
|
||||||
print_status_key_created (did_sub? 'B':'P', pk,
|
print_status_key_created (did_sub? 'B':'P', pk,
|
||||||
get_parameter_value (para, pHANDLE));
|
get_parameter_value (para, pHANDLE));
|
||||||
|
es_fflush (es_stdout);
|
||||||
|
if (any_adsk)
|
||||||
|
log_info (_("Note: The key has been created with one or more ADSK!\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
release_kbnode (pub_root);
|
release_kbnode (pub_root);
|
||||||
|
@ -310,6 +310,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);
|
||||||
|
@ -125,6 +125,8 @@ struct
|
|||||||
|
|
||||||
const char *def_new_key_algo;
|
const char *def_new_key_algo;
|
||||||
|
|
||||||
|
strlist_t def_new_key_adsks; /* Option --default-new-key-adsk. */
|
||||||
|
|
||||||
/* Options to be passed to the gpg-agent */
|
/* Options to be passed to the gpg-agent */
|
||||||
session_env_t session_env;
|
session_env_t session_env;
|
||||||
char *lc_ctype;
|
char *lc_ctype;
|
||||||
|
11
g10/packet.h
11
g10/packet.h
@ -68,6 +68,11 @@
|
|||||||
/* The usage bits which define encryption. */
|
/* The usage bits which define encryption. */
|
||||||
#define PUBKEY_USAGE_XENC_MASK (PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC)
|
#define PUBKEY_USAGE_XENC_MASK (PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC)
|
||||||
|
|
||||||
|
/* 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 \
|
||||||
@ -863,7 +868,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,
|
||||||
@ -885,7 +891,10 @@ 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 );
|
||||||
int cmp_public_keys( PKT_public_key *a, PKT_public_key *b );
|
int cmp_public_keys( PKT_public_key *a, PKT_public_key *b );
|
||||||
|
25
g10/sign.c
25
g10/sign.c
@ -49,10 +49,6 @@
|
|||||||
#define LF "\n"
|
#define LF "\n"
|
||||||
#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=0;
|
static int recipient_digest_algo=0;
|
||||||
@ -355,7 +351,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"
|
||||||
@ -864,7 +863,7 @@ write_signature_packets (ctrl_t ctrl,
|
|||||||
|
|
||||||
if (sig->version >= 4)
|
if (sig->version >= 4)
|
||||||
{
|
{
|
||||||
build_sig_subpkt_from_sig (sig, pk);
|
build_sig_subpkt_from_sig (sig, pk, 0);
|
||||||
mk_notation_policy_etc (sig, NULL, pk);
|
mk_notation_policy_etc (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);
|
||||||
@ -1687,6 +1686,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 )
|
||||||
{
|
{
|
||||||
@ -1709,7 +1710,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 (sig, pk, pksk);
|
mk_notation_policy_etc (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
|
||||||
@ -1759,7 +1760,7 @@ update_keysig_packet (ctrl_t ctrl,
|
|||||||
int digest_algo;
|
int digest_algo;
|
||||||
gcry_md_hd_t md;
|
gcry_md_hd_t md;
|
||||||
u32 pk_keyid[2], pksk_keyid[2];
|
u32 pk_keyid[2], pksk_keyid[2];
|
||||||
unsigned int signhints;
|
unsigned int signhints = 0;
|
||||||
|
|
||||||
if ((!orig_sig || !pk || !pksk)
|
if ((!orig_sig || !pk || !pksk)
|
||||||
|| (orig_sig->sig_class >= 0x10 && orig_sig->sig_class <= 0x13 && !uid)
|
|| (orig_sig->sig_class >= 0x10 && orig_sig->sig_class <= 0x13 && !uid)
|
||||||
@ -1820,6 +1821,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. */
|
||||||
@ -1828,7 +1835,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