From 3fc69224b7b22ad1df1395ebcb21549384839cd1 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 21 Feb 2017 08:27:23 +0900 Subject: [PATCH] g10: Support primary key generation by keygrip. * g10/keygen.c (para_name): Add pKEYGRIP. (generate_keypair): Use pKEYGRIP for key generation. (do_generate_keypair): Call do_create_from_keygrip with pKEYGRIP. -- https://lists.gnupg.org/pipermail/gnupg-devel/2017-February/032591.html Reported-by: Alon Bar-Lev Suggested-by: Peter Lebbing Signed-off-by: NIIBE Yutaka --- g10/keygen.c | 272 +++++++++++++++++++++++++++++---------------------- 1 file changed, 156 insertions(+), 116 deletions(-) diff --git a/g10/keygen.c b/g10/keygen.c index 98ef29efb..e2bdfc144 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -89,7 +89,8 @@ enum para_name { pSERIALNO, pCARDBACKUPKEY, pHANDLE, - pKEYSERVER + pKEYSERVER, + pKEYGRIP }; struct para_data_s { @@ -3653,8 +3654,9 @@ read_parameter_file (ctrl_t ctrl, const char *fname ) { "Preferences", pPREFERENCES }, { "Revoker", pREVOKER }, { "Handle", pHANDLE }, - { "Keyserver", pKEYSERVER }, - { NULL, 0 } + { "Keyserver", pKEYSERVER }, + { "Keygrip", pKEYGRIP }, + { NULL, 0 } }; IOBUF fp; byte *line; @@ -4175,103 +4177,14 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname, else if (full) /* Full featured key generation. */ { int subkey_algo; - char *curve = NULL; + char *key_from_hexgrip = NULL; - /* Fixme: To support creating a primary key by keygrip we better - also define the keyword for the parameter file. Note that - the subkey case will never be asserted if a keygrip has been - given. */ - algo = ask_algo (ctrl, 0, &subkey_algo, &use, NULL); - if (subkey_algo) + algo = ask_algo (ctrl, 0, &subkey_algo, &use, &key_from_hexgrip); + if (key_from_hexgrip) { - /* Create primary and subkey at once. */ - both = 1; - if (algo == PUBKEY_ALGO_ECDSA - || algo == PUBKEY_ALGO_EDDSA - || algo == PUBKEY_ALGO_ECDH) - { - curve = ask_curve (&algo, &subkey_algo); - r = xmalloc_clear( sizeof *r + 20 ); - r->key = pKEYTYPE; - sprintf( r->u.value, "%d", algo); - r->next = para; - para = r; - nbits = 0; - r = xmalloc_clear (sizeof *r + strlen (curve)); - r->key = pKEYCURVE; - strcpy (r->u.value, curve); - r->next = para; - para = r; - } - else - { - r = xmalloc_clear( sizeof *r + 20 ); - r->key = pKEYTYPE; - sprintf( r->u.value, "%d", algo); - r->next = para; - para = r; - nbits = ask_keysize (algo, 0); - r = xmalloc_clear( sizeof *r + 20 ); - r->key = pKEYLENGTH; - sprintf( r->u.value, "%u", nbits); - r->next = para; - para = r; - } - r = xmalloc_clear( sizeof *r + 20 ); - r->key = pKEYUSAGE; - strcpy( r->u.value, "sign" ); - r->next = para; - para = r; - - r = xmalloc_clear( sizeof *r + 20 ); - r->key = pSUBKEYTYPE; - sprintf( r->u.value, "%d", subkey_algo); - r->next = para; - para = r; - r = xmalloc_clear( sizeof *r + 20 ); - r->key = pSUBKEYUSAGE; - strcpy( r->u.value, "encrypt" ); - r->next = para; - para = r; - - if (algo == PUBKEY_ALGO_ECDSA - || algo == PUBKEY_ALGO_EDDSA - || algo == PUBKEY_ALGO_ECDH) - { - if (algo == PUBKEY_ALGO_EDDSA - && subkey_algo == PUBKEY_ALGO_ECDH) - { - /* Need to switch to a different curve for the - encryption key. */ - xfree (curve); - curve = xstrdup ("Curve25519"); - } - r = xmalloc_clear (sizeof *r + strlen (curve)); - r->key = pSUBKEYCURVE; - strcpy (r->u.value, curve); - r->next = para; - para = r; - } - } - else /* Create only a single key. */ - { - /* For ECC we need to ask for the curve before storing the - algo because ask_curve may change the algo. */ - if (algo == PUBKEY_ALGO_ECDSA - || algo == PUBKEY_ALGO_EDDSA - || algo == PUBKEY_ALGO_ECDH) - { - curve = ask_curve (&algo, NULL); - r = xmalloc_clear (sizeof *r + strlen (curve)); - r->key = pKEYCURVE; - strcpy (r->u.value, curve); - r->next = para; - para = r; - } - r = xmalloc_clear( sizeof *r + 20 ); r->key = pKEYTYPE; - sprintf( r->u.value, "%d", algo ); + sprintf( r->u.value, "%d", algo); r->next = para; para = r; @@ -4286,26 +4199,144 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname, r->next = para; para = r; } - nbits = 0; - } - if (algo == PUBKEY_ALGO_ECDSA - || algo == PUBKEY_ALGO_EDDSA - || algo == PUBKEY_ALGO_ECDH) - { - /* The curve has already been set. */ + r = xmalloc_clear( sizeof *r + 40 ); + r->key = pKEYGRIP; + strcpy (r->u.value, key_from_hexgrip); + r->next = para; + para = r; + + xfree (key_from_hexgrip); } else { - nbits = ask_keysize (both? subkey_algo : algo, nbits); - r = xmalloc_clear( sizeof *r + 20 ); - r->key = both? pSUBKEYLENGTH : pKEYLENGTH; - sprintf( r->u.value, "%u", nbits); - r->next = para; - para = r; - } + char *curve = NULL; - xfree (curve); + if (subkey_algo) + { + /* Create primary and subkey at once. */ + both = 1; + if (algo == PUBKEY_ALGO_ECDSA + || algo == PUBKEY_ALGO_EDDSA + || algo == PUBKEY_ALGO_ECDH) + { + curve = ask_curve (&algo, &subkey_algo); + r = xmalloc_clear( sizeof *r + 20 ); + r->key = pKEYTYPE; + sprintf( r->u.value, "%d", algo); + r->next = para; + para = r; + nbits = 0; + r = xmalloc_clear (sizeof *r + strlen (curve)); + r->key = pKEYCURVE; + strcpy (r->u.value, curve); + r->next = para; + para = r; + } + else + { + r = xmalloc_clear( sizeof *r + 20 ); + r->key = pKEYTYPE; + sprintf( r->u.value, "%d", algo); + r->next = para; + para = r; + nbits = ask_keysize (algo, 0); + r = xmalloc_clear( sizeof *r + 20 ); + r->key = pKEYLENGTH; + sprintf( r->u.value, "%u", nbits); + r->next = para; + para = r; + } + r = xmalloc_clear( sizeof *r + 20 ); + r->key = pKEYUSAGE; + strcpy( r->u.value, "sign" ); + r->next = para; + para = r; + + r = xmalloc_clear( sizeof *r + 20 ); + r->key = pSUBKEYTYPE; + sprintf( r->u.value, "%d", subkey_algo); + r->next = para; + para = r; + r = xmalloc_clear( sizeof *r + 20 ); + r->key = pSUBKEYUSAGE; + strcpy( r->u.value, "encrypt" ); + r->next = para; + para = r; + + if (algo == PUBKEY_ALGO_ECDSA + || algo == PUBKEY_ALGO_EDDSA + || algo == PUBKEY_ALGO_ECDH) + { + if (algo == PUBKEY_ALGO_EDDSA + && subkey_algo == PUBKEY_ALGO_ECDH) + { + /* Need to switch to a different curve for the + encryption key. */ + xfree (curve); + curve = xstrdup ("Curve25519"); + } + r = xmalloc_clear (sizeof *r + strlen (curve)); + r->key = pSUBKEYCURVE; + strcpy (r->u.value, curve); + r->next = para; + para = r; + } + } + else /* Create only a single key. */ + { + /* For ECC we need to ask for the curve before storing the + algo because ask_curve may change the algo. */ + if (algo == PUBKEY_ALGO_ECDSA + || algo == PUBKEY_ALGO_EDDSA + || algo == PUBKEY_ALGO_ECDH) + { + curve = ask_curve (&algo, NULL); + r = xmalloc_clear (sizeof *r + strlen (curve)); + r->key = pKEYCURVE; + strcpy (r->u.value, curve); + r->next = para; + para = r; + } + + r = xmalloc_clear( sizeof *r + 20 ); + r->key = pKEYTYPE; + sprintf( r->u.value, "%d", algo ); + r->next = para; + para = r; + + if (use) + { + r = xmalloc_clear( sizeof *r + 25 ); + r->key = pKEYUSAGE; + sprintf( r->u.value, "%s%s%s", + (use & PUBKEY_USAGE_SIG)? "sign ":"", + (use & PUBKEY_USAGE_ENC)? "encrypt ":"", + (use & PUBKEY_USAGE_AUTH)? "auth":"" ); + r->next = para; + para = r; + } + nbits = 0; + } + + if (algo == PUBKEY_ALGO_ECDSA + || algo == PUBKEY_ALGO_EDDSA + || algo == PUBKEY_ALGO_ECDH) + { + /* The curve has already been set. */ + } + else + { + nbits = ask_keysize (both? subkey_algo : algo, nbits); + r = xmalloc_clear( sizeof *r + 20 ); + r->key = both? pSUBKEYLENGTH : pKEYLENGTH; + sprintf( r->u.value, "%u", nbits); + r->next = para; + para = r; + } + + xfree (curve); + } } else /* Default key generation. */ { @@ -4547,6 +4578,9 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para, int did_sub = 0; u32 timestamp; char *cache_nonce = NULL; + int algo; + u32 expire; + const char *key_from_hexgrip = NULL; if (outctrl->dryrun) { @@ -4612,20 +4646,26 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para, node of the subkey but that is more work than just to pass the current timestamp. */ - if (!card) - err = do_create (get_parameter_algo( para, pKEYTYPE, NULL ), + algo = get_parameter_algo( para, pKEYTYPE, NULL ); + expire = get_parameter_u32( para, pKEYEXPIRE ); + key_from_hexgrip = get_parameter_value (para, pKEYGRIP); + if (key_from_hexgrip) + err = do_create_from_keygrip (ctrl, algo, key_from_hexgrip, + pub_root, timestamp, expire, 0); + else if (!card) + err = do_create (algo, get_parameter_uint( para, pKEYLENGTH ), get_parameter_value (para, pKEYCURVE), pub_root, timestamp, - get_parameter_u32( para, pKEYEXPIRE ), 0, + expire, 0, outctrl->keygen_flags, get_parameter_passphrase (para), &cache_nonce, NULL); else - err = gen_card_key (1, get_parameter_algo( para, pKEYTYPE, NULL ), + err = gen_card_key (1, algo, 1, pub_root, ×tamp, - get_parameter_u32 (para, pKEYEXPIRE)); + expire); /* Get the pointer to the generated public key packet. */ if (!err)