mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-03 22:56:33 +02: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 ed118e2ed5
)
and modified to adjust to other code changes
This commit is contained in:
parent
7eb39815bd
commit
eafe175320
12 changed files with 495 additions and 55 deletions
184
g10/keygen.c
184
g10/keygen.c
|
@ -91,6 +91,7 @@ enum para_name {
|
|||
pKEYSERVER,
|
||||
pKEYGRIP,
|
||||
pSUBKEYGRIP,
|
||||
pADSK /* this uses u.adsk */
|
||||
};
|
||||
|
||||
struct para_data_s {
|
||||
|
@ -102,6 +103,7 @@ struct para_data_s {
|
|||
u32 creation;
|
||||
unsigned int usage;
|
||||
struct revocation_key revkey;
|
||||
PKT_public_key *adsk; /* used with key == pADSK */
|
||||
char value[1];
|
||||
} u;
|
||||
};
|
||||
|
@ -246,22 +248,26 @@ 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;
|
||||
|
||||
build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1);
|
||||
if (use & PUBKEY_USAGE_RENC)
|
||||
buf[1] |= 0x04;
|
||||
if (use & PUBKEY_USAGE_TIME)
|
||||
buf[1] |= 0x08;
|
||||
build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, buf[1]? 2: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
|
||||
* used for the primary key. */
|
||||
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;
|
||||
|
||||
|
@ -1224,7 +1238,7 @@ write_keybinding (ctrl_t ctrl, kbnode_t root,
|
|||
oduap.pk = sub_pk;
|
||||
err = make_keysig_packet (ctrl, &sig, pri_pk, NULL, sub_pk, pri_psk, 0x18,
|
||||
0, timestamp, 0,
|
||||
keygen_add_key_flags_and_expire, &oduap,
|
||||
keygen_add_key_flags_from_oduap, &oduap,
|
||||
cache_nonce);
|
||||
if (err)
|
||||
{
|
||||
|
@ -3693,6 +3707,9 @@ release_parameter_list (struct para_data_s *r)
|
|||
r2 = r->next;
|
||||
if (r->key == pPASSPHRASE && *r->u.value)
|
||||
wipememory (r->u.value, strlen (r->u.value));
|
||||
else if (r->key == pADSK)
|
||||
free_public_key (r->u.adsk);
|
||||
|
||||
xfree (r);
|
||||
}
|
||||
}
|
||||
|
@ -3889,7 +3906,8 @@ prepare_desig_revoker (ctrl_t ctrl, const char *name)
|
|||
}
|
||||
|
||||
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);
|
||||
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. */
|
||||
static int
|
||||
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 *
|
||||
get_parameter_revkey (struct para_data_s *para, enum para_name key,
|
||||
unsigned int idx)
|
||||
get_parameter_revkey (struct para_data_s *para, 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;
|
||||
}
|
||||
|
||||
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
|
||||
proc_parameter_file (ctrl_t ctrl, struct para_data_s *para, const char *fname,
|
||||
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;
|
||||
size_t n;
|
||||
char *p;
|
||||
strlist_t sl;
|
||||
strlist_t sl, slr;
|
||||
int is_default = 0;
|
||||
int have_user_id = 0;
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (r && *r->u.value)
|
||||
{
|
||||
|
@ -5243,6 +5349,7 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
|||
u32 expire;
|
||||
const char *key_from_hexgrip = NULL;
|
||||
unsigned int idx;
|
||||
int any_adsk = 0;
|
||||
|
||||
if (outctrl->dryrun)
|
||||
{
|
||||
|
@ -5345,11 +5452,11 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
|
|||
}
|
||||
|
||||
/* Write all signatures specifying designated revokers. */
|
||||
for (idx=0;
|
||||
!err && (revkey = get_parameter_revkey (para, pREVOKER, idx));
|
||||
idx++)
|
||||
err = write_direct_sig (ctrl, pub_root, pri_psk,
|
||||
revkey, timestamp, cache_nonce);
|
||||
for (idx=0; !err && (revkey = get_parameter_revkey (para, idx)); idx++)
|
||||
{
|
||||
err = write_direct_sig (ctrl, pub_root, pri_psk,
|
||||
revkey, timestamp, cache_nonce);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* 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. */
|
||||
{
|
||||
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);
|
||||
|
||||
/* Get rid of the first empty packet. */
|
||||
commit_kbnode (&pub_root);
|
||||
|
||||
if (!opt.batch)
|
||||
{
|
||||
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;
|
||||
print_status_key_created (did_sub? 'B':'P', pk,
|
||||
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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue