diff options
Diffstat (limited to '')
-rw-r--r-- | g10/keygen.c | 1256 |
1 files changed, 459 insertions, 797 deletions
diff --git a/g10/keygen.c b/g10/keygen.c index 836b559f6..89f5e032d 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -132,15 +132,12 @@ static int mdc_available,ks_modify; static void do_generate_keypair( struct para_data_s *para, struct output_control_s *outctrl, int card ); -static int write_keyblock( IOBUF out, KBNODE node ); -static int gen_card_key (int algo, int keyno, int is_primary, - KBNODE pub_root, KBNODE sec_root, - PKT_secret_key **ret_sk, - u32 *timestamp, - u32 expireval, struct para_data_s *para); +static int write_keyblock (iobuf_t out, kbnode_t node); +static int gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root, + u32 *timestamp, u32 expireval, + struct para_data_s *para); static int gen_card_key_with_backup (int algo, int keyno, int is_primary, - KBNODE pub_root, KBNODE sec_root, - u32 timestamp, + kbnode_t pub_root, u32 timestamp, u32 expireval, struct para_data_s *para, const char *backup_dir); @@ -227,43 +224,46 @@ do_add_key_flags (PKT_signature *sig, unsigned int use) int -keygen_add_key_expire( PKT_signature *sig, void *opaque ) +keygen_add_key_expire (PKT_signature *sig, void *opaque) { - PKT_public_key *pk = opaque; - byte buf[8]; - u32 u; - - if( pk->expiredate ) { - if(pk->expiredate > pk->timestamp) - u= pk->expiredate - pk->timestamp; - else - u= 1; - - buf[0] = (u >> 24) & 0xff; - buf[1] = (u >> 16) & 0xff; - buf[2] = (u >> 8) & 0xff; - buf[3] = u & 0xff; - build_sig_subpkt( sig, SIGSUBPKT_KEY_EXPIRE, buf, 4 ); + PKT_public_key *pk = opaque; + byte buf[8]; + u32 u; + + if (pk->expiredate) + { + if (pk->expiredate > pk->timestamp) + u = pk->expiredate - pk->timestamp; + else + u = 1; + + buf[0] = (u >> 24) & 0xff; + buf[1] = (u >> 16) & 0xff; + buf[2] = (u >> 8) & 0xff; + buf[3] = u & 0xff; + build_sig_subpkt (sig, SIGSUBPKT_KEY_EXPIRE, buf, 4); + } + else + { + /* Make sure we don't leave a key expiration subpacket lying + around */ + delete_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE); } - else - { - /* Make sure we don't leave a key expiration subpacket lying - around */ - delete_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE); - } - return 0; + return 0; } + static int keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque) { - struct opaque_data_usage_and_pk *oduap = opaque; - - do_add_key_flags (sig, oduap->usage); - return keygen_add_key_expire (sig, oduap->pk); + struct opaque_data_usage_and_pk *oduap = opaque; + + do_add_key_flags (sig, oduap->usage); + return keygen_add_key_expire (sig, oduap->pk); } + static int set_one_pref (int val, int type, const char *item, byte *buf, int *nbuf) { @@ -697,19 +697,18 @@ keygen_upd_std_prefs (PKT_signature *sig, void *opaque) /**************** * Add preference to the self signature packet. * This is only called for packets with version > 3. - */ int -keygen_add_std_prefs( PKT_signature *sig, void *opaque ) +keygen_add_std_prefs (PKT_signature *sig, void *opaque) { - PKT_public_key *pk = opaque; - - do_add_key_flags (sig, pk->pubkey_usage); - keygen_add_key_expire( sig, opaque ); - keygen_upd_std_prefs (sig, opaque); - keygen_add_keyserver_url(sig,NULL); - - return 0; + PKT_public_key *pk = opaque; + + do_add_key_flags (sig, pk->pubkey_usage); + keygen_add_key_expire (sig, opaque ); + keygen_upd_std_prefs (sig, opaque); + keygen_add_keyserver_url (sig,NULL); + + return 0; } int @@ -778,23 +777,23 @@ keygen_add_notations(PKT_signature *sig,void *opaque) } int -keygen_add_revkey(PKT_signature *sig, void *opaque) +keygen_add_revkey (PKT_signature *sig, void *opaque) { - struct revocation_key *revkey=opaque; + struct revocation_key *revkey = opaque; byte buf[2+MAX_FINGERPRINT_LEN]; - buf[0]=revkey->class; - buf[1]=revkey->algid; - memcpy(&buf[2],revkey->fpr,MAX_FINGERPRINT_LEN); + buf[0] = revkey->class; + buf[1] = revkey->algid; + memcpy (&buf[2], revkey->fpr, MAX_FINGERPRINT_LEN); - build_sig_subpkt(sig,SIGSUBPKT_REV_KEY,buf,2+MAX_FINGERPRINT_LEN); + build_sig_subpkt (sig, SIGSUBPKT_REV_KEY, buf, 2+MAX_FINGERPRINT_LEN); - /* All sigs with revocation keys set are nonrevocable */ - sig->flags.revocable=0; + /* All sigs with revocation keys set are nonrevocable. */ + sig->flags.revocable = 0; buf[0] = 0; - build_sig_subpkt( sig, SIGSUBPKT_REVOCABLE, buf, 1 ); + build_sig_subpkt (sig, SIGSUBPKT_REVOCABLE, buf, 1); - parse_revkeys(sig); + parse_revkeys (sig); return 0; } @@ -803,115 +802,118 @@ keygen_add_revkey(PKT_signature *sig, void *opaque) /* Create a back-signature. If TIMESTAMP is not NULL, use it for the signature creation time. */ -int -make_backsig (PKT_signature *sig,PKT_public_key *pk, - PKT_public_key *sub_pk,PKT_secret_key *sub_sk, +gpg_error_t +make_backsig (PKT_signature *sig, PKT_public_key *pk, + PKT_public_key *sub_pk, PKT_public_key *sub_psk, u32 timestamp) { + gpg_error_t err; PKT_signature *backsig; - int rc; - cache_public_key(sub_pk); + cache_public_key (sub_pk); - rc = make_keysig_packet (&backsig, pk, NULL, sub_pk, sub_sk, 0x19, - 0, 0, timestamp, 0, NULL, NULL); - if(rc) - log_error("make_keysig_packet failed for backsig: %s\n",g10_errstr(rc)); + err = make_keysig_packet (&backsig, pk, NULL, sub_pk, sub_psk, 0x19, + 0, 0, timestamp, 0, NULL, NULL); + if (err) + log_error ("make_keysig_packet failed for backsig: %s\n", g10_errstr(err)); else { /* Get it into a binary packed form. */ - IOBUF backsig_out=iobuf_temp(); + IOBUF backsig_out = iobuf_temp(); PACKET backsig_pkt; - init_packet(&backsig_pkt); - backsig_pkt.pkttype=PKT_SIGNATURE; - backsig_pkt.pkt.signature=backsig; - rc=build_packet(backsig_out,&backsig_pkt); - free_packet(&backsig_pkt); - if(rc) - log_error("build_packet failed for backsig: %s\n",g10_errstr(rc)); + init_packet (&backsig_pkt); + backsig_pkt.pkttype = PKT_SIGNATURE; + backsig_pkt.pkt.signature = backsig; + err = build_packet (backsig_out, &backsig_pkt); + free_packet (&backsig_pkt); + if (err) + log_error ("build_packet failed for backsig: %s\n", g10_errstr(err)); else { - size_t pktlen=0; - byte *buf=iobuf_get_temp_buffer(backsig_out); + size_t pktlen = 0; + byte *buf = iobuf_get_temp_buffer (backsig_out); - /* Remove the packet header */ + /* Remove the packet header. */ if(buf[0]&0x40) { - if(buf[1]<192) + if (buf[1] < 192) { - pktlen=buf[1]; - buf+=2; - } - else if(buf[1]<224) + pktlen = buf[1]; + buf += 2; + } + else if(buf[1] < 224) { - pktlen=(buf[1]-192)*256; - pktlen+=buf[2]+192; - buf+=3; + pktlen = (buf[1]-192)*256; + pktlen += buf[2]+192; + buf += 3; } - else if(buf[1]==255) + else if (buf[1] == 255) { - pktlen =buf[2] << 24; - pktlen|=buf[3] << 16; - pktlen|=buf[4] << 8; - pktlen|=buf[5]; - buf+=6; + pktlen = buf[2] << 24; + pktlen |= buf[3] << 16; + pktlen |= buf[4] << 8; + pktlen |= buf[5]; + buf += 6; } else - BUG(); + BUG (); } else { - int mark=1; + int mark = 1; - switch(buf[0]&3) + switch (buf[0]&3) { case 3: - BUG(); + BUG (); break; case 2: - pktlen =buf[mark++] << 24; - pktlen|=buf[mark++] << 16; + pktlen = buf[mark++] << 24; + pktlen |= buf[mark++] << 16; case 1: - pktlen|=buf[mark++] << 8; + pktlen |= buf[mark++] << 8; case 0: - pktlen|=buf[mark++]; + pktlen |= buf[mark++]; } - buf+=mark; + buf += mark; } /* Now make the binary blob into a subpacket. */ - build_sig_subpkt(sig,SIGSUBPKT_SIGNATURE,buf,pktlen); + build_sig_subpkt (sig, SIGSUBPKT_SIGNATURE, buf, pktlen); - iobuf_close(backsig_out); + iobuf_close (backsig_out); } } - - return rc; + + return err; } -static int -write_direct_sig (KBNODE root, KBNODE pub_root, PKT_secret_key *sk, - struct revocation_key *revkey, u32 timestamp) +/* Write a direct key signature to the first key in ROOT using the key + PSK. REVKEY is describes the direct key signature and TIMESTAMP is + the timestamp to set on the signature. */ +static gpg_error_t +write_direct_sig (KBNODE root, PKT_public_key *psk, + struct revocation_key *revkey, u32 timestamp) { + gpg_error_t err; PACKET *pkt; PKT_signature *sig; - int rc=0; KBNODE node; PKT_public_key *pk; - if( opt.verbose ) - log_info(_("writing direct signature\n")); + if (opt.verbose) + log_info (_("writing direct signature\n")); /* Get the pk packet from the pub_tree. */ - node = find_kbnode( pub_root, PKT_PUBLIC_KEY ); - if( !node ) - BUG(); + node = find_kbnode (root, PKT_PUBLIC_KEY); + if (!node) + BUG (); pk = node->pkt->pkt.public_key; /* We have to cache the key, so that the verification of the @@ -919,48 +921,54 @@ write_direct_sig (KBNODE root, KBNODE pub_root, PKT_secret_key *sk, cache_public_key (pk); /* Make the signature. */ - rc = make_keysig_packet (&sig,pk,NULL,NULL,sk,0x1F, - 0, 0, timestamp, 0, - keygen_add_revkey, revkey); - if( rc ) + err = make_keysig_packet (&sig, pk, NULL,NULL, psk, 0x1F, + 0, 0, timestamp, 0, + keygen_add_revkey, revkey); + if (err) { - log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); - return rc; + log_error ("make_keysig_packet failed: %s\n", g10_errstr (err) ); + return err; } - pkt = xmalloc_clear( sizeof *pkt ); + pkt = xmalloc_clear (sizeof *pkt); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; - add_kbnode( root, new_kbnode( pkt ) ); - return rc; + add_kbnode (root, new_kbnode (pkt)); + return err; } -static int -write_selfsigs( KBNODE sec_root, KBNODE pub_root, PKT_secret_key *sk, - unsigned int use, u32 timestamp ) + +/* Write a self-signature to the first user id in ROOT using the key + PSK. USE and TIMESTAMP give the extra data we need for the + signature. */ +static gpg_error_t +write_selfsigs (KBNODE root, PKT_public_key *psk, + unsigned int use, u32 timestamp) { + gpg_error_t err; PACKET *pkt; PKT_signature *sig; PKT_user_id *uid; - int rc=0; KBNODE node; PKT_public_key *pk; - if( opt.verbose ) - log_info(_("writing self signature\n")); + if (opt.verbose) + log_info (_("writing self signature\n")); /* Get the uid packet from the list. */ - node = find_kbnode( pub_root, PKT_USER_ID ); - if( !node ) + node = find_kbnode (root, PKT_USER_ID); + if (!node) BUG(); /* No user id packet in tree. */ uid = node->pkt->pkt.user_id; /* Get the pk packet from the pub_tree. */ - node = find_kbnode( pub_root, PKT_PUBLIC_KEY ); - if( !node ) + node = find_kbnode (root, PKT_PUBLIC_KEY); + if (!node) BUG(); pk = node->pkt->pkt.public_key; + + /* The usage has not yet been set - do it now. */ pk->pubkey_usage = use; /* We have to cache the key, so that the verification of the @@ -968,48 +976,45 @@ write_selfsigs( KBNODE sec_root, KBNODE pub_root, PKT_secret_key *sk, cache_public_key (pk); /* Make the signature. */ - rc = make_keysig_packet (&sig, pk, uid, NULL, sk, 0x13, - 0, 0, timestamp, 0, - keygen_add_std_prefs, pk); - if( rc ) + err = make_keysig_packet (&sig, pk, uid, NULL, psk, 0x13, + 0, 0, timestamp, 0, + keygen_add_std_prefs, pk); + if (err) { - log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); - return rc; + log_error ("make_keysig_packet failed: %s\n", g10_errstr (err)); + return err; } - pkt = xmalloc_clear( sizeof *pkt ); + pkt = xmalloc_clear (sizeof *pkt); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; - add_kbnode( sec_root, new_kbnode( pkt ) ); + add_kbnode (root, new_kbnode (pkt)); - pkt = xmalloc_clear( sizeof *pkt ); - pkt->pkttype = PKT_SIGNATURE; - pkt->pkt.signature = copy_signature(NULL,sig); - add_kbnode( pub_root, new_kbnode( pkt ) ); - return rc; + return err; } /* Write the key binding signature. If TIMESTAMP is not NULL use the - signature creation times. */ + signature creation time. PRI_PSK is the key use for signing. + SUB_PSK is a key used to create a back-signature; that one is only + used if USE has the PUBKEY_USAGE_SIG capability. */ static int -write_keybinding (KBNODE root, KBNODE pub_root, - PKT_secret_key *pri_sk, PKT_secret_key *sub_sk, +write_keybinding (KBNODE root, PKT_public_key *pri_psk, PKT_public_key *sub_psk, unsigned int use, u32 timestamp) { + gpg_error_t err; PACKET *pkt; PKT_signature *sig; - int rc=0; KBNODE node; 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")); - /* Get the pk packet from the pub_tree. */ - node = find_kbnode ( pub_root, PKT_PUBLIC_KEY ); - if ( !node ) + /* Get the primary pk packet from the tree. */ + node = find_kbnode (root, PKT_PUBLIC_KEY); + if (!node) BUG(); pri_pk = node->pkt->pkt.public_key; @@ -1019,9 +1024,9 @@ write_keybinding (KBNODE root, KBNODE pub_root, /* Find the last subkey. */ sub_pk = NULL; - for (node=pub_root; node; node = node->next ) + for (node = root; node; node = node->next ) { - if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) sub_pk = node->pkt->pkt.public_key; } if (!sub_pk) @@ -1030,28 +1035,28 @@ write_keybinding (KBNODE root, KBNODE pub_root, /* Make the signature. */ oduap.usage = use; oduap.pk = sub_pk; - rc = make_keysig_packet (&sig, pri_pk, NULL, sub_pk, pri_sk, 0x18, - 0, 0, timestamp, 0, - keygen_add_key_flags_and_expire, &oduap ); - if (rc) + err = make_keysig_packet (&sig, pri_pk, NULL, sub_pk, pri_psk, 0x18, + 0, 0, timestamp, 0, + keygen_add_key_flags_and_expire, &oduap); + if (err) { - log_error ("make_keysig_packet failed: %s\n", g10_errstr(rc) ); - return rc; + log_error ("make_keysig_packet failed: %s\n", g10_errstr (err)); + return err; } /* Make a backsig. */ - if (use&PUBKEY_USAGE_SIG) + if (use & PUBKEY_USAGE_SIG) { - rc = make_backsig (sig, pri_pk, sub_pk, sub_sk, timestamp); - if (rc) - return rc; + err = make_backsig (sig, pri_pk, sub_pk, sub_psk, timestamp); + if (err) + return err; } pkt = xmalloc_clear ( sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; add_kbnode (root, new_kbnode (pkt) ); - return rc; + return err; } @@ -1106,71 +1111,76 @@ key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, } + +/* Common code for the key generation fucntion gen_xxx. */ static int -genhelp_protect (DEK *dek, STRING2KEY *s2k, PKT_secret_key *sk) +common_gen (const char *keyparms, int algo, const char *algoelem, + kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey) { - int rc = 0; - - if (dek) + int err; + PACKET *pkt; + PKT_public_key *pk; + gcry_sexp_t s_key; + + err = agent_genkey (NULL, keyparms, &s_key); + if (err) + { + log_error ("agent_genkey failed: %s\n", gpg_strerror (err) ); + return err; + } + + pk = xtrycalloc (1, sizeof *pk); + if (!pk) { - sk->protect.algo = dek->algo; - sk->protect.s2k = *s2k; - rc = protect_secret_key (sk, dek); - if (rc) - log_error ("protect_secret_key failed: %s\n", gpg_strerror (rc) ); + err = gpg_error_from_syserror (); + gcry_sexp_release (s_key); + return err; } - return rc; -} + pk->timestamp = timestamp; + pk->version = 4; + if (expireval) + pk->expiredate = pk->timestamp + expireval; + pk->pubkey_algo = algo; -static void -genhelp_factors (gcry_sexp_t misc_key_info, KBNODE sec_root) -{ - (void)misc_key_info; - (void)sec_root; -#if 0 /* Not used anymore */ - size_t n; - char *buf; + err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem); + if (err) + { + log_error ("key_from_sexp failed: %s\n", gpg_strerror (err) ); + gcry_sexp_release (s_key); + free_public_key (pk); + return err; + } + gcry_sexp_release (s_key); - if (misc_key_info) + pkt = xtrycalloc (1, sizeof *pkt); + if (!pkt) { - /* DSA: don't know whether it makes sense to have the factors, so for now - we store them in the secret keyring (but they are not secret) - p = 2 * q * f1 * f2 * ... * fn - We store only f1 to f_n-1; fn can be calculated because p and q - are known. */ - n = gcry_sexp_sprint (misc_key_info, 0, NULL, 0); - buf = xmalloc (n+4); - strcpy (buf, "#::"); - n = gcry_sexp_sprint (misc_key_info, 0, buf+3, n); - if (n) - { - n += 3; - add_kbnode (sec_root, make_comment_node_from_buffer (buf, n)); - } - xfree (buf); - gcry_sexp_release (misc_key_info); + err = gpg_error_from_syserror (); + free_public_key (pk); + return err; } -#endif + + pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY; + pkt->pkt.public_key = pk; + add_kbnode (pub_root, new_kbnode (pkt)); + + return 0; } -/* Generate an Elgamal encryption key pair. TIMESTAMP is the creatuion - time to be put into the key structure. */ +/* + * Generate an Elgamal key. + */ static int -gen_elg (int algo, unsigned int nbits, - KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, +gen_elg (int algo, unsigned int nbits, KBNODE pub_root, u32 timestamp, u32 expireval, int is_subkey) { - int rc; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - gcry_sexp_t s_parms, s_key; - gcry_sexp_t misc_key_info; + int err; + char *keyparms; + char nbitsstr[35]; - assert( is_ELGAMAL(algo) ); + assert (is_ELGAMAL (algo)); if (nbits < 512) { @@ -1184,104 +1194,36 @@ gen_elg (int algo, unsigned int nbits, log_info (_("keysize rounded up to %u bits\n"), nbits ); } - - rc = gcry_sexp_build ( &s_parms, NULL, - "(genkey(%s(nbits %d)))", - algo == GCRY_PK_ELG_E ? "openpgp-elg" : - algo == GCRY_PK_ELG ? "elg" : "x-oops" , - (int)nbits); - if (rc) - log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc)); - - rc = gcry_pk_genkey (&s_key, s_parms); - gcry_sexp_release (s_parms); - if (rc) - { - log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) ); - return rc; - } - - sk = xmalloc_clear( sizeof *sk ); - pk = xmalloc_clear( sizeof *pk ); - sk->timestamp = pk->timestamp = timestamp; - sk->version = pk->version = 4; - if (expireval) - { - sk->expiredate = pk->expiredate = sk->timestamp + expireval; - } - sk->pubkey_algo = pk->pubkey_algo = algo; - - rc = key_from_sexp (pk->pkey, s_key, "public-key", "pgy"); - if (rc) - { - log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) ); - gcry_sexp_release (s_key); - free_secret_key (sk); - free_public_key (pk); - return rc; - } - rc = key_from_sexp (sk->skey, s_key, "private-key", "pgyx"); - if (rc) - { - log_error("key_from_sexp failed: %s\n", gpg_strerror (rc) ); - gcry_sexp_release (s_key); - free_secret_key (sk); - free_public_key (pk); - return rc; - } - misc_key_info = gcry_sexp_find_token (s_key, "misc-key-info", 0); - gcry_sexp_release (s_key); - - sk->is_protected = 0; - sk->protect.algo = 0; - - sk->csum = checksum_mpi (sk->skey[3]); - if (ret_sk) /* Return an unprotected version of the sk. */ - *ret_sk = copy_secret_key ( NULL, sk ); - - rc = genhelp_protect (dek, s2k, sk); - if (rc) + snprintf (nbitsstr, sizeof nbitsstr, "%u", nbits); + keyparms = xtryasprintf ("(genkey(%s(nbits %zu:%s)))", + algo == GCRY_PK_ELG_E ? "openpgp-elg" : + algo == GCRY_PK_ELG ? "elg" : "x-oops" , + strlen (nbitsstr), nbitsstr); + if (!keyparms) + err = gpg_error_from_syserror (); + else { - free_public_key (pk); - free_secret_key (sk); - gcry_sexp_release (misc_key_info); - return rc; + err = common_gen (keyparms, algo, "pgy", + pub_root, timestamp, expireval, is_subkey); + xfree (keyparms); } - - pkt = xmalloc_clear (sizeof *pkt); - pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY; - pkt->pkt.public_key = pk; - add_kbnode (pub_root, new_kbnode( pkt )); - /* Don't know whether it makes sense to have access to the factors, - so for now we store them in the secret keyring (but they are not - secret). */ - pkt = xmalloc_clear (sizeof *pkt); - pkt->pkttype = is_subkey ? PKT_SECRET_SUBKEY : PKT_SECRET_KEY; - pkt->pkt.secret_key = sk; - add_kbnode (sec_root, new_kbnode( pkt )); - - genhelp_factors (misc_key_info, sec_root); - - return 0; + return err; } -/**************** - * Generate a DSA key +/* + * Generate an DSA key */ -static int -gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, +static gpg_error_t +gen_dsa (unsigned int nbits, KBNODE pub_root, u32 timestamp, u32 expireval, int is_subkey) { - int rc; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - gcry_sexp_t s_parms, s_key; - gcry_sexp_t misc_key_info; + int err; unsigned int qbits; + char *keyparms; + char nbitsstr[35]; + char qbitsstr[35]; if ( nbits < 512) { @@ -1334,84 +1276,21 @@ gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, log_info (_("WARNING: some OpenPGP programs can't" " handle a DSA key with this digest size\n")); - rc = gcry_sexp_build (&s_parms, NULL, - "(genkey(dsa(nbits %d)(qbits %d)))", - (int)nbits, (int)qbits); - if (rc) - log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc)); - - rc = gcry_pk_genkey (&s_key, s_parms); - gcry_sexp_release (s_parms); - if (rc) - { - log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) ); - return rc; - } - - sk = xmalloc_clear( sizeof *sk ); - pk = xmalloc_clear( sizeof *pk ); - sk->timestamp = pk->timestamp = timestamp; - sk->version = pk->version = 4; - if (expireval) - sk->expiredate = pk->expiredate = sk->timestamp + expireval; - sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA; - - rc = key_from_sexp (pk->pkey, s_key, "public-key", "pqgy"); - if (rc) - { - log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc)); - gcry_sexp_release (s_key); - free_public_key(pk); - free_secret_key(sk); - return rc; - } - rc = key_from_sexp (sk->skey, s_key, "private-key", "pqgyx"); - if (rc) - { - log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) ); - gcry_sexp_release (s_key); - free_public_key(pk); - free_secret_key(sk); - return rc; - } - misc_key_info = gcry_sexp_find_token (s_key, "misc-key-info", 0); - gcry_sexp_release (s_key); - - sk->is_protected = 0; - sk->protect.algo = 0; - - sk->csum = checksum_mpi ( sk->skey[4] ); - if( ret_sk ) /* return an unprotected version of the sk */ - *ret_sk = copy_secret_key( NULL, sk ); - - rc = genhelp_protect (dek, s2k, sk); - if (rc) + snprintf (nbitsstr, sizeof nbitsstr, "%u", nbits); + snprintf (qbitsstr, sizeof qbitsstr, "%u", qbits); + keyparms = xtryasprintf ("(genkey(dsa(nbits %zu:%s)(qbits %zu:%s)))", + strlen (nbitsstr), nbitsstr, + strlen (qbitsstr), qbitsstr); + if (!keyparms) + err = gpg_error_from_syserror (); + else { - free_public_key (pk); - free_secret_key (sk); - gcry_sexp_release (misc_key_info); - return rc; + err = common_gen (keyparms, PUBKEY_ALGO_DSA, "pqgy", + pub_root, timestamp, expireval, is_subkey); + xfree (keyparms); } - pkt = xmalloc_clear(sizeof *pkt); - pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY; - pkt->pkt.public_key = pk; - add_kbnode(pub_root, new_kbnode( pkt )); - - /* Don't know whether it makes sense to have the factors, so for now - * we store them in the secret keyring (but they are not secret) - * p = 2 * q * f1 * f2 * ... * fn - * We store only f1 to f_n-1; fn can be calculated because p and q - * are known. - */ - pkt = xmalloc_clear(sizeof *pkt); - pkt->pkttype = is_subkey ? PKT_SECRET_SUBKEY : PKT_SECRET_KEY; - pkt->pkt.secret_key = sk; - add_kbnode(sec_root, new_kbnode( pkt )); - - genhelp_factors (misc_key_info, sec_root); - - return 0; + return err; } @@ -1419,15 +1298,12 @@ gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, * Generate an RSA key. */ static int -gen_rsa (int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, +gen_rsa (int algo, unsigned int nbits, KBNODE pub_root, u32 timestamp, u32 expireval, int is_subkey) { - int rc; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - gcry_sexp_t s_parms, s_key; + int err; + char *keyparms; + char nbitsstr[35]; assert (is_RSA(algo)); @@ -1446,79 +1322,19 @@ gen_rsa (int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, log_info (_("keysize rounded up to %u bits\n"), nbits ); } - rc = gcry_sexp_build (&s_parms, NULL, - "(genkey(rsa(nbits %d)))", - (int)nbits); - if (rc) - log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc)); - - rc = gcry_pk_genkey (&s_key, s_parms); - gcry_sexp_release (s_parms); - if (rc) - { - log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) ); - return rc; - } - - sk = xmalloc_clear( sizeof *sk ); - pk = xmalloc_clear( sizeof *pk ); - sk->timestamp = pk->timestamp = timestamp; - sk->version = pk->version = 4; - if (expireval) - { - sk->expiredate = pk->expiredate = sk->timestamp + expireval; - } - sk->pubkey_algo = pk->pubkey_algo = algo; - - rc = key_from_sexp (pk->pkey, s_key, "public-key", "ne"); - if (rc) - { - log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc)); - gcry_sexp_release (s_key); - free_public_key(pk); - free_secret_key(sk); - return rc; - } - rc = key_from_sexp (sk->skey, s_key, "private-key", "nedpqu"); - if (rc) - { - log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) ); - gcry_sexp_release (s_key); - free_public_key(pk); - free_secret_key(sk); - return rc; - } - gcry_sexp_release (s_key); - - sk->is_protected = 0; - sk->protect.algo = 0; - - sk->csum = checksum_mpi (sk->skey[2] ); - sk->csum += checksum_mpi (sk->skey[3] ); - sk->csum += checksum_mpi (sk->skey[4] ); - sk->csum += checksum_mpi (sk->skey[5] ); - if( ret_sk ) /* return an unprotected version of the sk */ - *ret_sk = copy_secret_key( NULL, sk ); - - rc = genhelp_protect (dek, s2k, sk); - if (rc) + snprintf (nbitsstr, sizeof nbitsstr, "%u", nbits); + keyparms = xtryasprintf ("(genkey(rsa(nbits %zu:%s)))", + strlen (nbitsstr), nbitsstr); + if (!keyparms) + err = gpg_error_from_syserror (); + else { - free_public_key (pk); - free_secret_key (sk); - return rc; + err = common_gen (keyparms, algo, "ne", + pub_root, timestamp, expireval, is_subkey); + xfree (keyparms); } - pkt = xmalloc_clear(sizeof *pkt); - pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY; - pkt->pkt.public_key = pk; - add_kbnode(pub_root, new_kbnode( pkt )); - - pkt = xmalloc_clear(sizeof *pkt); - pkt->pkttype = is_subkey ? PKT_SECRET_SUBKEY : PKT_SECRET_KEY; - pkt->pkt.secret_key = sk; - add_kbnode(sec_root, new_kbnode( pkt )); - - return 0; + return err; } @@ -2310,32 +2126,30 @@ do_ask_passphrase (STRING2KEY **ret_s2k, int mode, int *r_canceled) /* Basic key generation. Here we divert to the actual generation routines based on the requested algorithm. */ static int -do_create (int algo, unsigned int nbits, KBNODE pub_root, KBNODE sec_root, - DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, +do_create (int algo, unsigned int nbits, KBNODE pub_root, u32 timestamp, u32 expiredate, int is_subkey ) { - int rc=0; + gpg_error_t err; - if( !opt.batch ) - tty_printf(_( + /* Fixme: The entropy collecting message should be moved to a + libgcrypt progress handler. */ + if (!opt.batch) + tty_printf (_( "We need to generate a lot of random bytes. It is a good idea to perform\n" "some other action (type on the keyboard, move the mouse, utilize the\n" "disks) during the prime generation; this gives the random number\n" "generator a better chance to gain enough entropy.\n") ); - if( algo == PUBKEY_ALGO_ELGAMAL_E ) - rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k, sk, - timestamp, expiredate, is_subkey); - else if( algo == PUBKEY_ALGO_DSA ) - rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, - timestamp, expiredate, is_subkey); - else if( algo == PUBKEY_ALGO_RSA ) - rc = gen_rsa(algo, nbits, pub_root, sec_root, dek, s2k, sk, - timestamp, expiredate, is_subkey); + if (algo == PUBKEY_ALGO_ELGAMAL_E) + err = gen_elg (algo, nbits, pub_root, timestamp, expiredate, is_subkey); + else if (algo == PUBKEY_ALGO_DSA) + err = gen_dsa (nbits, pub_root, timestamp, expiredate, is_subkey); + else if (algo == PUBKEY_ALGO_RSA) + err = gen_rsa (algo, nbits, pub_root, timestamp, expiredate, is_subkey); else BUG(); - return rc; + return err; } @@ -2533,20 +2347,6 @@ get_parameter_uint( struct para_data_s *para, enum para_name key ) return get_parameter_u32( para, key ); } -static DEK * -get_parameter_dek( struct para_data_s *para, enum para_name key ) -{ - struct para_data_s *r = get_parameter( para, key ); - return r? r->u.dek : NULL; -} - -static STRING2KEY * -get_parameter_s2k( struct para_data_s *para, enum para_name key ) -{ - struct para_data_s *r = get_parameter( para, key ); - return r? r->u.s2k : NULL; -} - static struct revocation_key * get_parameter_revkey( struct para_data_s *para, enum para_name key ) { @@ -3050,8 +2850,6 @@ generate_keypair (const char *fname, const char *card_serialno, { unsigned int nbits; char *uid = NULL; - DEK *dek; - STRING2KEY *s2k; int algo; unsigned int use; int both = 0; @@ -3059,7 +2857,6 @@ generate_keypair (const char *fname, const char *card_serialno, struct para_data_s *para = NULL; struct para_data_s *r; struct output_control_s outctrl; - int canceled; memset( &outctrl, 0, sizeof( outctrl ) ); @@ -3217,26 +3014,7 @@ generate_keypair (const char *fname, const char *card_serialno, r->next = para; para = r; - canceled = 0; - dek = card_serialno? NULL : do_ask_passphrase (&s2k, 0, &canceled); - if( dek ) - { - r = xmalloc_clear( sizeof *r ); - r->key = pPASSPHRASE_DEK; - r->u.dek = dek; - r->next = para; - para = r; - r = xmalloc_clear( sizeof *r ); - r->key = pPASSPHRASE_S2K; - r->u.s2k = s2k; - r->next = para; - para = r; - } - - if (canceled) - log_error (_("Key generation canceled.\n")); - else - proc_parameter_file( para, "[internal]", &outctrl, !!card_serialno); + proc_parameter_file( para, "[internal]", &outctrl, !!card_serialno); release_parameter_list( para ); } @@ -3356,16 +3134,16 @@ static void do_generate_keypair (struct para_data_s *para, struct output_control_s *outctrl, int card) { + gpg_error_t err; KBNODE pub_root = NULL; - KBNODE sec_root = NULL; - PKT_secret_key *pri_sk = NULL, *sub_sk = NULL; const char *s; + PKT_public_key *pri_psk = NULL; + PKT_public_key *sub_psk = NULL; struct revocation_key *revkey; - int rc; int did_sub = 0; u32 timestamp; - if( outctrl->dryrun ) + if (outctrl->dryrun) { log_info("dry-run mode - key generation skipped\n"); return; @@ -3403,51 +3181,9 @@ do_generate_keypair (struct para_data_s *para, push_armor_filter (outctrl->pub.afx, outctrl->pub.stream); } } - if (outctrl->sec.newfname) - { - mode_t oldmask; - - iobuf_close(outctrl->sec.stream); - outctrl->sec.stream = NULL; - if (outctrl->sec.fname) - iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, - 0, (char*)outctrl->sec.fname); - xfree( outctrl->sec.fname ); - outctrl->sec.fname = outctrl->sec.newfname; - outctrl->sec.newfname = NULL; - - oldmask = umask (077); - if (is_secured_filename (outctrl->sec.fname) ) - { - outctrl->sec.stream = NULL; - gpg_err_set_errno (EPERM); - } - else - outctrl->sec.stream = iobuf_create( outctrl->sec.fname ); - umask (oldmask); - if (!outctrl->sec.stream) - { - log_error(_("can't create `%s': %s\n"), outctrl->sec.newfname, - strerror(errno) ); - return; - } - if (opt.armor) - { - outctrl->sec.afx->what = 5; - push_armor_filter (outctrl->sec.afx, outctrl->sec.stream); - } - } assert( outctrl->pub.stream ); - assert( outctrl->sec.stream ); if (opt.verbose) - { - log_info (_("writing public key to `%s'\n"), outctrl->pub.fname ); - if (card) - log_info (_("writing secret key stub to `%s'\n"), - outctrl->sec.fname); - else - log_info(_("writing secret key to `%s'\n"), outctrl->sec.fname ); - } + log_info (_("writing public key to `%s'\n"), outctrl->pub.fname ); } @@ -3457,7 +3193,6 @@ do_generate_keypair (struct para_data_s *para, deleted. The very first packet must always be a KEY packet. */ start_tree (&pub_root); - start_tree (&sec_root); timestamp = get_parameter_u32 (para, pKEYCREATIONDATE); if (!timestamp) @@ -3473,42 +3208,31 @@ do_generate_keypair (struct para_data_s *para, current timestamp. */ if (!card) - { - rc = do_create (get_parameter_algo( para, pKEYTYPE, NULL ), - get_parameter_uint( para, pKEYLENGTH ), - pub_root, sec_root, - get_parameter_dek( para, pPASSPHRASE_DEK ), - get_parameter_s2k( para, pPASSPHRASE_S2K ), - &pri_sk, - timestamp, - get_parameter_u32( para, pKEYEXPIRE ), 0 ); - } + err = do_create (get_parameter_algo( para, pKEYTYPE, NULL ), + get_parameter_uint( para, pKEYLENGTH ), + pub_root, + timestamp, + get_parameter_u32( para, pKEYEXPIRE ), 0 ); else - { - rc = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, sec_root, NULL, - ×tamp, - get_parameter_u32 (para, pKEYEXPIRE), para); - if (!rc) - { - pri_sk = sec_root->next->pkt->pkt.secret_key; - assert (pri_sk); - } - } + err = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, + ×tamp, + get_parameter_u32 (para, pKEYEXPIRE), para); - if(!rc && (revkey=get_parameter_revkey(para,pREVOKER))) + /* Get the pointer to the generated public key packet. */ + if (!err) { - rc = write_direct_sig (pub_root, pub_root, pri_sk, revkey, timestamp); - if (!rc) - rc = write_direct_sig (sec_root, pub_root, pri_sk, revkey, timestamp); + pri_psk = pub_root->next->pkt->pkt.public_key; + assert (pri_psk); } - if( !rc && (s=get_parameter_value(para, pUSERID)) ) + if (!err && (revkey = get_parameter_revkey (para, pREVOKER))) + err = write_direct_sig (pub_root, pri_psk, revkey, timestamp); + + if (!err && (s = get_parameter_value (para, pUSERID))) { write_uid (pub_root, s ); - write_uid (sec_root, s ); - - rc = write_selfsigs (sec_root, pub_root, pri_sk, - get_parameter_uint (para, pKEYUSAGE), timestamp); + err = write_selfsigs (pub_root, pri_psk, + get_parameter_uint (para, pKEYUSAGE), timestamp); } /* Write the auth key to the card before the encryption key. This @@ -3518,32 +3242,36 @@ do_generate_keypair (struct para_data_s *para, actually an encryption type. In this case, the auth key is an RSA key so it succeeds. */ - if (!rc && card && get_parameter (para, pAUTHKEYTYPE)) + if (!err && card && get_parameter (para, pAUTHKEYTYPE)) { - rc = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root, sec_root, NULL, - ×tamp, - get_parameter_u32 (para, pKEYEXPIRE), para); - - if (!rc) - rc = write_keybinding (pub_root, pub_root, pri_sk, sub_sk, - PUBKEY_USAGE_AUTH, timestamp); - if (!rc) - rc = write_keybinding (sec_root, pub_root, pri_sk, sub_sk, - PUBKEY_USAGE_AUTH, timestamp); + err = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root, + ×tamp, + get_parameter_u32 (para, pKEYEXPIRE), para); + if (!err) + err = write_keybinding (pub_root, pri_psk, NULL, + PUBKEY_USAGE_AUTH, timestamp); } - if( !rc && get_parameter( para, pSUBKEYTYPE ) ) + if (!err && get_parameter (para, pSUBKEYTYPE)) { + sub_psk = NULL; if (!card) { - rc = do_create( get_parameter_algo( para, pSUBKEYTYPE, NULL ), - get_parameter_uint( para, pSUBKEYLENGTH ), - pub_root, sec_root, - get_parameter_dek( para, pPASSPHRASE_DEK ), - get_parameter_s2k( para, pPASSPHRASE_S2K ), - &sub_sk, - timestamp, - get_parameter_u32( para, pSUBKEYEXPIRE ), 1 ); + err = do_create (get_parameter_algo (para, pSUBKEYTYPE, NULL), + get_parameter_uint (para, pSUBKEYLENGTH), + pub_root, + timestamp, + get_parameter_u32 (para, pSUBKEYEXPIRE), 1 ); + /* Get the pointer to the generated public subkey packet. */ + if (!err) + { + kbnode_t node; + + for (node = pub_root; node; node = node->next) + if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) + sub_psk = node->pkt->pkt.public_key; + assert (sub_psk); + } } else { @@ -3552,95 +3280,60 @@ do_generate_keypair (struct para_data_s *para, /* A backup of the encryption key has been requested. Generate the key in software and import it then to the card. Write a backup file. */ - rc = gen_card_key_with_backup (PUBKEY_ALGO_RSA, 2, 0, - pub_root, sec_root, - timestamp, - get_parameter_u32 (para, - pKEYEXPIRE), - para, s); + err = gen_card_key_with_backup (PUBKEY_ALGO_RSA, 2, 0, + pub_root, + timestamp, + get_parameter_u32 (para, + pKEYEXPIRE), + para, s); } else { - rc = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root, sec_root, - NULL, - ×tamp, - get_parameter_u32 (para, pKEYEXPIRE), para); + err = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root, + ×tamp, + get_parameter_u32 (para, pKEYEXPIRE), para); } } - if( !rc ) - rc = write_keybinding(pub_root, pub_root, pri_sk, sub_sk, - get_parameter_uint (para, pSUBKEYUSAGE), - timestamp); - if( !rc ) - rc = write_keybinding(sec_root, pub_root, pri_sk, sub_sk, - get_parameter_uint (para, pSUBKEYUSAGE), - timestamp); + if (!err) + err = write_keybinding (pub_root, pri_psk, sub_psk, + get_parameter_uint (para, pSUBKEYUSAGE), + timestamp); did_sub = 1; } - if (!rc && outctrl->use_files) /* Direct write to specified files. */ + if (!err && outctrl->use_files) /* Direct write to specified files. */ { - rc = write_keyblock( outctrl->pub.stream, pub_root ); - if (rc) - log_error ("can't write public key: %s\n", g10_errstr(rc) ); - if (!rc) - { - rc = write_keyblock( outctrl->sec.stream, sec_root ); - if(rc) - log_error ("can't write secret key: %s\n", g10_errstr(rc) ); - } + err = write_keyblock (outctrl->pub.stream, pub_root); + if (err) + log_error ("can't write public key: %s\n", g10_errstr (err)); } - else if (!rc) /* Write to the standard keyrings. */ + else if (!err) /* Write to the standard keyrings. */ { KEYDB_HANDLE pub_hd = keydb_new (0); - KEYDB_HANDLE sec_hd = keydb_new (1); - rc = keydb_locate_writable (pub_hd, NULL); - if (rc) + err = keydb_locate_writable (pub_hd, NULL); + if (err) log_error (_("no writable public keyring found: %s\n"), - g10_errstr (rc)); - - if (!rc) - { - rc = keydb_locate_writable (sec_hd, NULL); - if (rc) - log_error (_("no writable secret keyring found: %s\n"), - g10_errstr (rc)); - } + g10_errstr (err)); - if (!rc && opt.verbose) + if (!err && opt.verbose) { log_info (_("writing public key to `%s'\n"), keydb_get_resource_name (pub_hd)); - if (card) - log_info (_("writing secret key stub to `%s'\n"), - keydb_get_resource_name (sec_hd)); - else - log_info (_("writing secret key to `%s'\n"), - keydb_get_resource_name (sec_hd)); } - if (!rc) + if (!err) { - rc = keydb_insert_keyblock (pub_hd, pub_root); - if (rc) + err = keydb_insert_keyblock (pub_hd, pub_root); + if (err) log_error (_("error writing public keyring `%s': %s\n"), - keydb_get_resource_name (pub_hd), g10_errstr(rc)); + keydb_get_resource_name (pub_hd), g10_errstr(err)); } - if (!rc) - { - rc = keydb_insert_keyblock (sec_hd, sec_root); - if (rc) - log_error (_("error writing secret keyring `%s': %s\n"), - keydb_get_resource_name (pub_hd), g10_errstr(rc)); - } - keydb_release (pub_hd); - keydb_release (sec_hd); - if (!rc) + if (!err) { int no_enc_rsa; PKT_public_key *pk; @@ -3653,8 +3346,8 @@ do_generate_keypair (struct para_data_s *para, pk = find_kbnode (pub_root, PKT_PUBLIC_KEY)->pkt->pkt.public_key; - keyid_from_pk(pk,pk->main_keyid); - register_trusted_keyid(pk->main_keyid); + keyid_from_pk (pk, pk->main_keyid); + register_trusted_keyid (pk->main_keyid); update_ownertrust (pk, ((get_ownertrust (pk) & ~TRUST_MASK) | TRUST_ULTIMATE )); @@ -3663,7 +3356,7 @@ do_generate_keypair (struct para_data_s *para, { tty_printf (_("public and secret key created and signed.\n") ); tty_printf ("\n"); - list_keyblock(pub_root,0,1,NULL); + list_keyblock (pub_root, 0, 1, NULL); } @@ -3680,13 +3373,13 @@ do_generate_keypair (struct para_data_s *para, } } - if (rc) + if (err) { if (opt.batch) - log_error ("key generation failed: %s\n", g10_errstr(rc) ); + log_error ("key generation failed: %s\n", g10_errstr(err) ); else - tty_printf (_("Key generation failed: %s\n"), g10_errstr(rc) ); - write_status_errcode (card? "card_key_generate":"key_generate", rc); + tty_printf (_("Key generation failed: %s\n"), g10_errstr(err) ); + write_status_error (card? "card_key_generate":"key_generate", err); print_status_key_not_created ( get_parameter_value (para, pHANDLE) ); } else @@ -3696,99 +3389,91 @@ do_generate_keypair (struct para_data_s *para, print_status_key_created (did_sub? 'B':'P', pk, get_parameter_value (para, pHANDLE)); } - release_kbnode( pub_root ); - release_kbnode( sec_root ); - if (pri_sk && !card) /* The unprotected secret key unless we */ - free_secret_key (pri_sk); /* have a shallow copy in card mode. */ - if (sub_sk) - free_secret_key(sub_sk); + release_kbnode (pub_root); } -/* Add a new subkey to an existing key. Returns true if a new key has +/* Add a new subkey to an existing key. Returns 0 if a new key has been generated and put into the keyblocks. */ -int -generate_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock) +gpg_error_t +generate_subkeypair (KBNODE keyblock) { - int okay=0, rc=0; - KBNODE node; - PKT_secret_key *pri_sk = NULL, *sub_sk = NULL; + gpg_error_t err = 0; + kbnode_t node; + PKT_public_key *pri_psk = NULL; + PKT_public_key *sub_psk = NULL; int algo; unsigned int use; u32 expire; - unsigned nbits; - char *passphrase = NULL; - DEK *dek = NULL; - STRING2KEY *s2k = NULL; + unsigned int nbits; u32 cur_time; - int ask_pass = 0; - int canceled; - /* Break out the primary secret key. */ - node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); - if( !node ) + /* Break out the primary key. */ + node = find_kbnode (keyblock, PKT_PUBLIC_KEY); + if (!node) { - log_error ("Oops; secret key not found anymore!\n"); + log_error ("Oops; primary key missing in keyblock!\n"); + err = gpg_error (GPG_ERR_BUG); goto leave; } - - /* Make a copy of the sk to keep the protected one in the keyblock. */ - pri_sk = copy_secret_key (NULL, node->pkt->pkt.secret_key); + pri_psk = node->pkt->pkt.public_key; - cur_time = make_timestamp(); + cur_time = make_timestamp (); - if (pri_sk->timestamp > cur_time) + if (pri_psk->timestamp > cur_time) { - ulong d = pri_sk->timestamp - cur_time; + ulong d = pri_psk->timestamp - cur_time; log_info ( d==1 ? _("key has been created %lu second " "in future (time warp or clock problem)\n") : _("key has been created %lu seconds " "in future (time warp or clock problem)\n"), d ); if (!opt.ignore_time_conflict) { - rc = G10ERR_TIME_CONFLICT; + err = gpg_error (GPG_ERR_TIME_CONFLICT); goto leave; } } - if (pri_sk->version < 4) + if (pri_psk->version < 4) { log_info (_("NOTE: creating subkeys for v3 keys " "is not OpenPGP compliant\n")); + err = gpg_error (GPG_ERR_CONFLICT); goto leave; } - if (pri_sk->is_protected && pri_sk->protect.s2k.mode == 1001) - { - tty_printf (_("Secret parts of primary key are not available.\n")); - rc = G10ERR_NO_SECKEY; - goto leave; - } - - - /* Unprotect to get the passphrase. */ - switch (is_secret_key_protected (pri_sk) ) - { - case -1: - rc = G10ERR_PUBKEY_ALGO; - break; - case 0: - tty_printf (_("This key is not protected.\n")); - break; - case -2: - tty_printf (_("Secret parts of primary key are stored on-card.\n")); - ask_pass = 1; - break; - default: - tty_printf (_("Key is protected.\n")); - rc = check_secret_key ( pri_sk, 0 ); - if (!rc) - passphrase = get_last_passphrase(); - break; - } - if (rc) - goto leave; +#warning ask gpg-agent on the availibility of the secret key + /* if (pri_sk->is_protected && pri_sk->protect.s2k.mode == 1001) */ + /* { */ + /* tty_printf (_("Secret parts of primary key are not available.\n")); */ + /* err = G10ERR_NO_SECKEY; */ + /* goto leave; */ + /* } */ + + + /* /\* Unprotect to get the passphrase. *\/ */ + /* switch (is_secret_key_protected (pri_sk) ) */ + /* { */ + /* case -1: */ + /* err = G10ERR_PUBKEY_ALGO; */ + /* break; */ + /* case 0: */ + /* tty_printf (_("This key is not protected.\n")); */ + /* break; */ + /* case -2: */ + /* tty_printf (_("Secret parts of primary key are stored on-card.\n")); */ + /* ask_pass = 1; */ + /* break; */ + /* default: */ + /* tty_printf (_("Key is protected.\n")); */ + /* err = check_secret_key ( pri_sk, 0 ); */ + /* if (!err) */ + /* passphrase = get_last_passphrase(); */ + /* break; */ + /* } */ + /* if (err) */ + /* goto leave; */ algo = ask_algo (1, NULL, &use); assert (algo); @@ -3796,52 +3481,31 @@ generate_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock) expire = ask_expire_interval (0, NULL); if (!cpr_enabled() && !cpr_get_answer_is_yes("keygen.sub.okay", _("Really create? (y/N) "))) - goto leave; - - canceled = 0; - if (ask_pass) - dek = do_ask_passphrase (&s2k, 0, &canceled); - else if (passphrase) { - s2k = xmalloc_secure ( sizeof *s2k ); - s2k->mode = opt.s2k_mode; - s2k->hash_algo = S2K_DIGEST_ALGO; - set_next_passphrase ( passphrase ); - dek = passphrase_to_dek (NULL, 0, opt.s2k_cipher_algo, s2k, 2, - NULL, NULL ); - } - - if (canceled) - rc = GPG_ERR_CANCELED; - - if (!rc) - rc = do_create (algo, nbits, pub_keyblock, sec_keyblock, - dek, s2k, &sub_sk, cur_time, expire, 1 ); - if (!rc) - rc = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, sub_sk, - use, cur_time); - if (!rc) - rc = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, sub_sk, - use, cur_time); - if (!rc) - { - okay = 1; - write_status_text (STATUS_KEY_CREATED, "S"); - } + err = gpg_error (GPG_ERR_CANCELED); + goto leave; + } + + err = do_create (algo, nbits, keyblock, cur_time, expire, 1); + if (err) + goto leave; + + /* Get the pointer to the generated public subkey packet. */ + for (node = keyblock; node; node = node->next) + if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) + sub_psk = node->pkt->pkt.public_key; + + /* Write the binding signature. */ + err = write_keybinding (keyblock, pri_psk, sub_psk, use, cur_time); + if (err) + goto leave; + + write_status_text (STATUS_KEY_CREATED, "S"); leave: - if (rc) - log_error (_("Key generation failed: %s\n"), g10_errstr(rc) ); - xfree (passphrase); - xfree (dek); - xfree (s2k); - /* Release the copy of the (now unprotected) secret keys. */ - if (pri_sk) - free_secret_key (pri_sk); - if (sub_sk) - free_secret_key (sub_sk); - set_next_passphrase (NULL); - return okay; + if (err) + log_error (_("Key generation failed: %s\n"), g10_errstr (err) ); + return err; } @@ -3851,8 +3515,9 @@ int generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock, int keyno, const char *serialno) { - int okay=0, rc=0; - KBNODE node; + gpg_error_t err = 0; + int okay = 0; + kbnode_t node; PKT_secret_key *pri_sk = NULL, *sub_sk; int algo; unsigned int use; @@ -3888,7 +3553,7 @@ generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock, "in future (time warp or clock problem)\n"), d ); if (!opt.ignore_time_conflict) { - rc = G10ERR_TIME_CONFLICT; + err = G10ERR_TIME_CONFLICT; goto leave; } } @@ -3904,19 +3569,19 @@ generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock, switch( is_secret_key_protected (pri_sk) ) { case -1: - rc = G10ERR_PUBKEY_ALGO; + err = G10ERR_PUBKEY_ALGO; break; case 0: tty_printf("This key is not protected.\n"); break; default: tty_printf("Key is protected.\n"); - rc = check_secret_key( pri_sk, 0 ); - if (!rc) + err = check_secret_key( pri_sk, 0 ); + if (!err) passphrase = get_last_passphrase(); break; } - if (rc) + if (err) goto leave; algo = PUBKEY_ALGO_RSA; @@ -3936,23 +3601,22 @@ generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock, /* Note, that depending on the backend, the card key generation may update CUR_TIME. */ - rc = gen_card_key (algo, keyno, 0, pub_keyblock, sec_keyblock, - &sub_sk, &cur_time, expire, para); - if (!rc) - rc = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, sub_sk, - use, cur_time); - if (!rc) - rc = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, sub_sk, + err = gen_card_key (algo, keyno, 0, pub_keyblock, &cur_time, expire, para); + if (!err) + err = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, sub_sk, + use, cur_time); + if (!err) + err = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, sub_sk, use, cur_time); - if (!rc) + if (!err) { okay = 1; write_status_text (STATUS_KEY_CREATED, "S"); } leave: - if (rc) - log_error (_("Key generation failed: %s\n"), g10_errstr(rc) ); + if (err) + log_error (_("Key generation failed: %s\n"), g10_errstr(err) ); xfree (passphrase); /* Release the copy of the (now unprotected) secret keys. */ if (pri_sk) @@ -3990,8 +3654,7 @@ write_keyblock( IOBUF out, KBNODE node ) /* Note that timestamp is an in/out arg. */ static int -gen_card_key (int algo, int keyno, int is_primary, - KBNODE pub_root, KBNODE sec_root, PKT_secret_key **ret_sk, +gen_card_key (int algo, int keyno, int is_primary, KBNODE pub_root, u32 *timestamp, u32 expireval, struct para_data_s *para) { #ifdef ENABLE_CARD_SUPPORT @@ -4070,7 +3733,7 @@ gen_card_key (int algo, int keyno, int is_primary, return 0; #else - return -1; + return gpg_error (GPG_ERR_NOT_SUPPORTED); #endif /*!ENABLE_CARD_SUPPORT*/ } @@ -4078,8 +3741,7 @@ gen_card_key (int algo, int keyno, int is_primary, static int gen_card_key_with_backup (int algo, int keyno, int is_primary, - KBNODE pub_root, KBNODE sec_root, - u32 timestamp, + KBNODE pub_root, u32 timestamp, u32 expireval, struct para_data_s *para, const char *backup_dir) { @@ -4240,7 +3902,7 @@ gen_card_key_with_backup (int algo, int keyno, int is_primary, return 0; #else - return -1; + return gpg_error (GPG_ERR_NOT_SUPPORTED); #endif /*!ENABLE_CARD_SUPPORT*/ } |