aboutsummaryrefslogtreecommitdiffstats
path: root/g10/keygen.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/keygen.c')
-rw-r--r--g10/keygen.c186
1 files changed, 156 insertions, 30 deletions
diff --git a/g10/keygen.c b/g10/keygen.c
index 26126cde7..19ec52f23 100644
--- a/g10/keygen.c
+++ b/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;
-
- build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1);
+ 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_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;
+
+ r = prepare_adsk (ctrl, sl->d);
+ if (!r)
+ return -1;
+ append_to_parameter (para, r);
+ }
- /* Make KEYCREATIONDATE from Creation-Date. */
+ /* 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);