From 6f7ed0590060cc013946e192f725545445e6c39f Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 29 Jul 2003 08:53:19 +0000 Subject: [PATCH] * gpgsm.c (main): Add secmem features and set the random seed file. (gpgsm_exit): Update the random seed file and enable debug output. * g10.c (main): Add secmem features and set the random seed file. (g10_exit): Update the random seed file. * parse-packet.c (parse_signature,read_protected_v3_mpi) (parse_key): Fixed use of mpi_set_opaque. * keygen.c (gen_card_key): Ditto. --- g10/ChangeLog | 23 ++ g10/comment.c | 13 +- g10/g10.c | 40 ++- g10/keygen.c | 640 +++++++++++++++++++++++++++++++-------------- g10/main.h | 1 + g10/parse-packet.c | 20 +- g10/seckey-cert.c | 2 +- g10/status.c | 23 +- 8 files changed, 510 insertions(+), 252 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 23a79cf72..335f28fdf 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,26 @@ +2003-07-29 Werner Koch + + * g10.c (main): Add secmem features and set the random seed file. + (g10_exit): Update the random seed file. + + * parse-packet.c (parse_signature,read_protected_v3_mpi) + (parse_key): Fixed use of mpi_set_opaque. + * keygen.c (gen_card_key): Ditto. + +2003-07-28 Werner Koch + + * status.c (progress_cb): Adjusted for use with Libcgrypt. + (set_status_fd): Register that callback. + + * keygen.c (smartcard_change_login_data): New. + (smartcard_change_lang): New. + (smartcard_change_sex): New. + (check_smartcard): Add menu entries to edit the above. + (gen_elg,gen_dsa,gen_rsa): Reimplemented in terms of Libgcrypt. + (genhelp_protect, genhelp_factors, key_from_sexp): New. + * comment.c (make_comment_node_from_buffer): New. + (make_comment_node): Reimplemented in terms of above. + 2003-07-27 Werner Koch Adjusted for gcry_mpi_print and gcry_mpi_scan API change. diff --git a/g10/comment.c b/g10/comment.c index ab5d2941e..b52104cd7 100644 --- a/g10/comment.c +++ b/g10/comment.c @@ -63,19 +63,24 @@ write_comment( iobuf_t out, const char *s ) KBNODE -make_comment_node( const char *s ) +make_comment_node_from_buffer (const char *s, size_t n) { PACKET *pkt; - size_t n = strlen(s); - pkt = xcalloc (1, sizeof *pkt ); + pkt = gcry_xcalloc( 1, sizeof *pkt ); pkt->pkttype = PKT_COMMENT; - pkt->pkt.comment = xmalloc ( sizeof *pkt->pkt.comment + n - 1 ); + pkt->pkt.comment = gcry_xmalloc( sizeof *pkt->pkt.comment + n - 1 ); pkt->pkt.comment->len = n; strcpy(pkt->pkt.comment->data, s); return new_kbnode( pkt ); } +KBNODE +make_comment_node( const char *s ) +{ + return make_comment_node_from_buffer (s, strlen (s)); +} + KBNODE make_mpi_comment_node( const char *s, gcry_mpi_t a ) diff --git a/g10/g10.c b/g10/g10.c index 2f0a78cd0..f89556184 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -32,6 +32,7 @@ #ifdef HAVE_STAT #include /* for stat() */ #endif +#include #define INCLUDED_BY_MAIN_MODULE 1 #include "gpg.h" @@ -1759,8 +1760,7 @@ main( int argc, char **argv ) break; case oCertDigestAlgo: cert_digest_string = xstrdup (pargs.r.ret_str); break; case oNoSecmemWarn: -#warning add secmem_get_flags -/* secmem_set_flags( secmem_get_flags() | 1 ); */ + gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); break; case oNoPermissionWarn: opt.no_perm_warn=1; break; case oNoMDCWarn: opt.no_mdc_warn=1; break; @@ -1993,9 +1993,6 @@ main( int argc, char **argv ) } #endif -#warning locking does not work - disabled - disable_dotlock (); - if (opt.verbose > 2) log_info ("using character set `%s'\n", get_native_charset ()); @@ -2026,10 +2023,7 @@ main( int argc, char **argv ) if( opt.batch ) tty_batchmode( 1 ); -#warning fix that -#if 0 - secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */ -#endif + gcry_control (GCRYCTL_RESUME_SECMEM_WARN); set_debug(); /* Do these after the switch(), so they can override settings. */ @@ -2274,10 +2268,7 @@ main( int argc, char **argv ) /* set the random seed file */ if( use_random_seed ) { char *p = make_filename(opt.homedir, "random_seed", NULL ); -#warning No random seed file yet -#if 0 - set_random_seed_file(p); -#endif + gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p); xfree (p); } @@ -2936,17 +2927,18 @@ emergency_cleanup (void) void g10_exit( int rc ) { - /* FIXME-XX update_random_seed_file(); */ -/* if( opt.debug & DBG_MEMSTAT_VALUE ) { */ -/* m_print_stats("on exit"); */ -/* random_dump_stats(); */ -/* } */ -/* if( opt.debug ) */ -/* secmem_dump_stats(); */ - gcry_control (GCRYCTL_TERM_SECMEM ); - rc = rc? rc : log_get_errorcount(0)? 2 : - g10_errors_seen? 1 : 0; - exit(rc ); + gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE); + if (opt.debug & DBG_MEMSTAT_VALUE) + { + gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); + gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); + } + if (opt.debug) + gcry_control (GCRYCTL_DUMP_SECMEM_STATS ); + emergency_cleanup (); + rc = rc? rc : log_get_errorcount(0)? 2 : + g10_errors_seen? 1 : 0; + exit (rc ); } diff --git a/g10/keygen.c b/g10/keygen.c index 515d4867a..210bbc897 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -740,86 +740,198 @@ write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, static int -gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, +key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, + const char *topname, const char *elems) +{ + gcry_sexp_t list, l2; + const char *s; + int i, idx; + int rc = 0; + + list = gcry_sexp_find_token (sexp, topname, 0); + if (!list) + return gpg_error (GPG_ERR_INV_OBJ); + l2 = gcry_sexp_cadr (list); + gcry_sexp_release (list); + list = l2; + if (!list) + return gpg_error (GPG_ERR_NO_OBJ); + + for (idx=0,s=elems; *s; s++, idx++) + { + l2 = gcry_sexp_find_token (list, s, 1); + if (!l2) + { + rc = gpg_error (GPG_ERR_NO_OBJ); /* required parameter not found */ + goto leave; + } + array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l2); + if (!array[idx]) + { + rc = gpg_error (GPG_ERR_INV_OBJ); /* required parameter invalid */ + goto leave; + } + } + gcry_sexp_release (list); + + leave: + if (rc) + { + for (i=0; iprotect.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) ); + } + + return rc; +} + +static void +genhelp_factors (gcry_sexp_t misc_key_info, KBNODE sec_root) +{ + size_t n; + char *buf; + + if (misc_key_info) + { + /* 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); + } +} + + +static int +gen_elg(int algo, unsigned int nbits, + KBNODE pub_root, KBNODE sec_root, DEK *dek, STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) { - int rc; - int i; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - gcry_mpi_t skey[4]; - gcry_mpi_t *factors; + 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; + + assert (is_ELGAMAL(algo)); - assert( is_ELGAMAL(algo) ); - - if( nbits < 512 ) { - nbits = 1024; - log_info(_("keysize invalid; using %u bits\n"), nbits ); + if (nbits < 512) + { + nbits = 1024; + log_info (_("keysize invalid; using %u bits\n"), nbits); } - if( (nbits % 32) ) { - nbits = ((nbits + 31) / 32) * 32; - log_info(_("keysize rounded up to %u bits\n"), nbits ); + if ((nbits % 32)) + { + nbits = ((nbits + 31) / 32) * 32; + log_info (_("keysize rounded up to %u bits\n"), nbits); } -#warning need to implement this - rc = -1 /*pubkey_generate( algo, nbits, skey, &factors )*/; - if( rc ) { - log_error("pubkey_generate failed: %s\n", gpg_strerror (rc) ); - return rc; + 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 = xcalloc (1, sizeof *sk ); - pk = xcalloc (1, sizeof *pk ); - sk->timestamp = pk->timestamp = make_timestamp(); - sk->version = pk->version = 4; - if( expireval ) { - sk->expiredate = pk->expiredate = sk->timestamp + expireval; + sk = xcalloc (1, sizeof *sk); + pk = xcalloc (1, sizeof *pk); + sk->timestamp = pk->timestamp = make_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); + return rc; } - sk->pubkey_algo = pk->pubkey_algo = algo; - pk->pkey[0] = mpi_copy( skey[0] ); - pk->pkey[1] = mpi_copy( skey[1] ); - pk->pkey[2] = mpi_copy( skey[2] ); - sk->skey[0] = skey[0]; - sk->skey[1] = skey[1]; - sk->skey[2] = skey[2]; - sk->skey[3] = skey[3]; - sk->is_protected = 0; - sk->protect.algo = 0; + 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); + return rc; + } + misc_key_info = gcry_sexp_find_token (s_key, "misc-key-info", 0); + gcry_sexp_release (s_key); - sk->csum = checksum_mpi( sk->skey[3] ); - if( ret_sk ) /* not a subkey: return an unprotected version of the sk */ - *ret_sk = copy_secret_key( NULL, sk ); + sk->is_protected = 0; + sk->protect.algo = 0; - if( dek ) { - 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) ); - free_public_key(pk); - free_secret_key(sk); - return rc; - } + sk->csum = checksum_mpi (sk->skey[3]); + if (ret_sk) /* not a subkey: return an unprotected version of the sk */ + *ret_sk = copy_secret_key (NULL, sk); + + rc = genhelp_protect (dek, s2k, sk); + if (rc) + { + free_public_key (pk); + free_secret_key (sk); + gcry_sexp_release (misc_key_info); + return rc; } - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; - 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) */ - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; - pkt->pkt.secret_key = sk; - add_kbnode(sec_root, new_kbnode( pkt )); - for(i=0; factors[i]; i++ ) - add_kbnode( sec_root, - make_mpi_comment_node("#:ELG_factor:", factors[i] )); - - return 0; + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; + 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) */ + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; + pkt->pkt.secret_key = sk; + add_kbnode(sec_root, new_kbnode( pkt )); + + genhelp_factors (misc_key_info, sec_root); + + return 0; } @@ -827,90 +939,96 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, * Generate a DSA key */ static int -gen_dsa(unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) +gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, + STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) { - int rc; - int i; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - gcry_mpi_t skey[5]; - gcry_mpi_t *factors; + 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; - if( nbits > 1024 || nbits < 512 ) { - nbits = 1024; - log_info(_("keysize invalid; using %u bits\n"), nbits ); + if (nbits > 1024 || nbits < 512) + { + nbits = 1024; + log_info(_("keysize invalid; using %u bits\n"), nbits); } - if( (nbits % 64) ) { - nbits = ((nbits + 63) / 64) * 64; - log_info(_("keysize rounded up to %u bits\n"), nbits ); + if ((nbits % 64)) + { + nbits = ((nbits + 63) / 64) * 64; + log_info (_("keysize rounded up to %u bits\n"), nbits); } -#warning need to implement this - rc = -1 /*pubkey_generate( PUBKEY_ALGO_DSA, nbits, skey, &factors )*/; - if( rc ) { - log_error("pubkey_generate failed: %s\n", gpg_strerror (rc) ); - return rc; + rc = gcry_sexp_build (&s_parms, NULL, + "(genkey(dsa(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 = xcalloc (1, sizeof *sk ); - pk = xcalloc (1, sizeof *pk ); - sk->timestamp = pk->timestamp = make_timestamp(); - sk->version = pk->version = 4; - if( expireval ) { - sk->expiredate = pk->expiredate = sk->timestamp + expireval; + sk = xcalloc (1, sizeof *sk ); + pk = xcalloc (1, sizeof *pk ); + sk->timestamp = pk->timestamp = make_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); + return rc; } - sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA; - pk->pkey[0] = mpi_copy( skey[0] ); - pk->pkey[1] = mpi_copy( skey[1] ); - pk->pkey[2] = mpi_copy( skey[2] ); - pk->pkey[3] = mpi_copy( skey[3] ); - sk->skey[0] = skey[0]; - sk->skey[1] = skey[1]; - sk->skey[2] = skey[2]; - sk->skey[3] = skey[3]; - sk->skey[4] = skey[4]; - sk->is_protected = 0; - sk->protect.algo = 0; + 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); + return rc; + } + misc_key_info = gcry_sexp_find_token (s_key, "misc-key-info", 0); + gcry_sexp_release (s_key); - sk->csum = checksum_mpi ( sk->skey[4] ); - if( ret_sk ) /* not a subkey: return an unprotected version of the sk */ - *ret_sk = copy_secret_key( NULL, sk ); + sk->is_protected = 0; + sk->protect.algo = 0; - if( dek ) { - 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) ); - free_public_key(pk); - free_secret_key(sk); - return rc; - } + sk->csum = checksum_mpi ( sk->skey[4] ); + if (ret_sk) /* not a subkey: return an unprotected version of the sk */ + *ret_sk = copy_secret_key( NULL, sk ); + + rc = genhelp_protect (dek, s2k, sk); + if (rc) + { + free_public_key (pk); + free_secret_key (sk); + gcry_sexp_release (misc_key_info); + return rc; } - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; - pkt->pkt.public_key = pk; - add_kbnode(pub_root, new_kbnode( pkt )); + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; + 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 = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; - pkt->pkt.secret_key = sk; - add_kbnode(sec_root, new_kbnode( pkt )); - for(i=1; factors[i]; i++ ) /* the first one is q */ - add_kbnode( sec_root, - make_mpi_comment_node("#:DSA_factor:", factors[i] )); + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; + pkt->pkt.secret_key = sk; + add_kbnode(sec_root, new_kbnode( pkt )); - return 0; + genhelp_factors (misc_key_info, sec_root); + + return 0; } @@ -921,81 +1039,93 @@ static int gen_rsa(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) { - int rc; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - gcry_mpi_t skey[6]; - gcry_mpi_t *factors; + int rc; + PACKET *pkt; + PKT_secret_key *sk; + PKT_public_key *pk; + gcry_sexp_t s_parms, s_key; - assert( is_RSA(algo) ); + assert (is_RSA(algo)); - if( nbits < 1024 ) { - nbits = 1024; - log_info(_("keysize invalid; using %u bits\n"), nbits ); + if (nbits < 1024) + { + nbits = 1024; + log_info(_("keysize invalid; using %u bits\n"), nbits); } - if( (nbits % 32) ) { - nbits = ((nbits + 31) / 32) * 32; - log_info(_("keysize rounded up to %u bits\n"), nbits ); + if ((nbits % 32)) + { + nbits = ((nbits + 31) / 32) * 32; + log_info (_("keysize rounded up to %u bits\n"), nbits); } -#warning need to implement this - rc = -1 /*pubkey_generate( algo, nbits, skey, &factors )*/; - if( rc ) { - log_error("pubkey_generate failed: %s\n", gpg_strerror (rc) ); - return rc; + 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 = xcalloc (1, sizeof *sk ); - pk = xcalloc (1, sizeof *pk ); - sk->timestamp = pk->timestamp = make_timestamp(); - sk->version = pk->version = 4; - if( expireval ) { - sk->expiredate = pk->expiredate = sk->timestamp + expireval; + sk = xcalloc (1, sizeof *sk ); + pk = xcalloc (1, sizeof *pk ); + sk->timestamp = pk->timestamp = make_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); + return rc; } - sk->pubkey_algo = pk->pubkey_algo = algo; - pk->pkey[0] = mpi_copy( skey[0] ); - pk->pkey[1] = mpi_copy( skey[1] ); - sk->skey[0] = skey[0]; - sk->skey[1] = skey[1]; - sk->skey[2] = skey[2]; - sk->skey[3] = skey[3]; - sk->skey[4] = skey[4]; - sk->skey[5] = skey[5]; - sk->is_protected = 0; - sk->protect.algo = 0; + 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); + return rc; + } + gcry_sexp_release (s_key); - 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 ) /* not a subkey: return an unprotected version of the sk */ - *ret_sk = copy_secret_key( NULL, sk ); + sk->is_protected = 0; + sk->protect.algo = 0; - if( dek ) { - 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) ); - free_public_key(pk); - free_secret_key(sk); - return rc; - } + 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) /* not a subkey: return an unprotected version of the sk */ + *ret_sk = copy_secret_key (NULL, sk); + + rc = genhelp_protect (dek, s2k, sk); + if (rc) + { + free_public_key (pk); + free_secret_key (sk); + return rc; } - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; - pkt->pkt.public_key = pk; - add_kbnode(pub_root, new_kbnode( pkt )); + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; + pkt->pkt.public_key = pk; + add_kbnode (pub_root, new_kbnode( pkt )); - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; - pkt->pkt.secret_key = sk; - add_kbnode(sec_root, new_kbnode( pkt )); + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; + pkt->pkt.secret_key = sk; + add_kbnode(sec_root, new_kbnode( pkt )); - return 0; + return 0; } @@ -1271,8 +1401,9 @@ ask_expire_interval(int object) tty_printf(_("%s expires at %s\n"), object==0?"Key":"Signature", asctimestamp((ulong)(curtime + interval) ) ); - /* FIXME: This check yields warning on alhas: - write a configure check and to this check here only for 32 bit machines */ + /* FIXME: This check yields warning some machines: write a + configure check and do this check here only for 32 bit + machines */ if( (time_t)((ulong)(curtime+interval)) < 0 ) tty_printf(_("Your system can't display dates beyond 2038.\n" "However, it will be correctly handled up to 2106.\n")); @@ -2803,6 +2934,97 @@ smartcard_change_url (const char *current_url) return rc; } +static int +smartcard_change_login_data (void) +{ + char *data; + int rc; + + data = cpr_get ("keygen.smartcard.login_data", + _("Login data (account name): ")); + if (!data) + return -1; + trim_spaces (data); + cpr_kill_prompt (); + + rc = agent_scd_setattr ("LOGIN-DATA", data, strlen (data) ); + if (rc) + log_error ("error setting login data: %s\n", gpg_strerror (rc)); + xfree (data); + return rc; +} + +static int +smartcard_change_lang (void) +{ + char *data, *p; + int rc; + + data = cpr_get ("keygen.smartcard.lang", + _("Language preferences: ")); + if (!data) + return -1; + trim_spaces (data); + cpr_kill_prompt (); + + if (strlen (data) > 8 || (strlen (data) & 1)) + { + tty_printf (_("Error: invalid length of preference string.\n")); + xfree (data); + return -1; + } + + for (p=data; *p && *p >= 'a' && *p <= 'z'; p++) + ; + if (*p) + { + tty_printf (_("Error: invalid characters in preference string.\n")); + xfree (data); + return -1; + } + + rc = agent_scd_setattr ("DISP-LANG", data, strlen (data) ); + if (rc) + log_error ("error setting lang: %s\n", gpg_strerror (rc)); + xfree (data); + return rc; +} + + +static int +smartcard_change_sex (void) +{ + char *data; + const char *str; + int rc; + + data = cpr_get ("keygen.smartcard.sex", + _("Sex ((M)ale, (F)emale or space): ")); + if (!data) + return -1; + trim_spaces (data); + cpr_kill_prompt (); + + if (!*data) + str = "9"; + else if ((*data == 'M' || *data == 'm') && !data[1]) + str = "1"; + else if ((*data == 'F' || *data == 'f') && !data[1]) + str = "2"; + else + { + tty_printf (_("Error: invalid response.\n")); + xfree (data); + return -1; + } + + rc = agent_scd_setattr ("DISP-SEX", str, 1 ); + if (rc) + log_error ("error setting sex: %s\n", gpg_strerror (rc)); + xfree (data); + return rc; +} + /* Return true if the SHA1 fingerprint FPR consists only of zeroes. */ static int @@ -2851,6 +3073,9 @@ check_smartcard (char **r_serialno) tty_printf ("\n" "N - change cardholder name\n" "U - change public key URL\n" + "D - change login data\n" + "L - change language preferences\n" + "S - change sex\n" "K - generate all keys\n" "Q - quit\n" "\n"); @@ -2871,6 +3096,21 @@ check_smartcard (char **r_serialno) if (!smartcard_change_url (info.pubkey_url)) reread = 1; } + else if ( *answer == 'D' || *answer == 'd') + { + if (!smartcard_change_login_data ()) + reread = 1; + } + else if ( *answer == 'L' || *answer == 'l') + { + if (!smartcard_change_lang ()) + reread = 1; + } + else if ( *answer == 'S' || *answer == 's') + { + if (!smartcard_change_sex ()) + reread = 1; + } else if ( *answer == 'K' || *answer == 'k') { if ( (info.fpr1valid && !fpr_is_zero (info.fpr1)) @@ -2972,9 +3212,9 @@ gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, sk->pubkey_algo = pk->pubkey_algo = algo; pk->pkey[0] = info.n; pk->pkey[1] = info.e; - sk->skey[0] = mpi_copy (pk->pkey[0]); - sk->skey[1] = mpi_copy (pk->pkey[1]); - sk->skey[2] = mpi_set_opaque (NULL, xstrdup ("dummydata"), 10); + sk->skey[0] = gcry_mpi_copy (pk->pkey[0]); + sk->skey[1] = gcry_mpi_copy (pk->pkey[1]); + sk->skey[2] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8); sk->is_protected = 1; sk->protect.s2k.mode = 1002; s = get_parameter_value (para, pSERIALNO); diff --git a/g10/main.h b/g10/main.h index cb81192d3..2e1377ea4 100644 --- a/g10/main.h +++ b/g10/main.h @@ -188,6 +188,7 @@ gcry_mpi_t encode_md_value( int pubkey_algo, MD_HANDLE md, int hash_algo, unsigned nbits, int v3compathack ); /*-- comment.c --*/ +KBNODE make_comment_node_from_buffer (const char *s, size_t n); KBNODE make_comment_node( const char *s ); KBNODE make_mpi_comment_node( const char *s, gcry_mpi_t a ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 57a6d3d7b..f70cc3f69 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1342,7 +1342,8 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, unknown_pubkey_warning( sig->pubkey_algo ); /* we store the plain material in data[0], so that we are able * to write it back with build_packet() */ - sig->data[0] = mpi_set_opaque(NULL, read_rest(inp, pktlen), pktlen ); + sig->data[0] = gcry_mpi_set_opaque(NULL, read_rest(inp, pktlen), + pktlen*8 ); pktlen = 0; } else { @@ -1446,7 +1447,7 @@ read_protected_v3_mpi (iobuf_t inp, unsigned long *length) } /* convert buffer into an opaque gcry_mpi_t */ - val = mpi_set_opaque (NULL, buf, p-buf); + val = gcry_mpi_set_opaque (NULL, buf, (p-buf)*8); return val; } @@ -1565,8 +1566,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, size_t snlen = 0; if( !npkey ) { - sk->skey[0] = mpi_set_opaque( NULL, - read_rest(inp, pktlen), pktlen ); + sk->skey[0] = gcry_mpi_set_opaque( NULL, read_rest(inp, pktlen), + pktlen*8 ); pktlen = 0; goto leave; } @@ -1744,15 +1745,16 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, if( sk->protect.s2k.mode == 1001 || sk->protect.s2k.mode == 1002 ) { /* better set some dummy stuff here */ - sk->skey[npkey] = mpi_set_opaque(NULL, xstrdup ("dummydata"), 10); + sk->skey[npkey] = gcry_mpi_set_opaque(NULL, xstrdup ("dummydata"), + 10*8); pktlen = 0; } else if( is_v4 && sk->is_protected ) { /* ugly; the length is encrypted too, so we read all * stuff up to the end of the packet into the first * skey element */ - sk->skey[npkey] = mpi_set_opaque(NULL, - read_rest(inp, pktlen), pktlen ); + sk->skey[npkey] = gcry_mpi_set_opaque(NULL, read_rest(inp, pktlen), + pktlen*8 ); pktlen = 0; if( list_mode ) { printf("\tencrypted stuff follows\n"); @@ -1792,8 +1794,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, PKT_public_key *pk = pkt->pkt.public_key; if( !npkey ) { - pk->pkey[0] = mpi_set_opaque( NULL, - read_rest(inp, pktlen), pktlen ); + pk->pkey[0] = gcry_mpi_set_opaque( NULL, read_rest(inp, pktlen), + pktlen*8 ); pktlen = 0; goto leave; } diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index c9bddd2ff..5a7db4c97 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -323,7 +323,7 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) return 0; if( !sk->is_protected ) { /* okay, apply the protection */ - CIPHER_HANDLE cipher_hd=NULL; + gcry_cipher_hd_t cipher_hd=NULL; if( openpgp_cipher_test_algo( sk->protect.algo ) ) { diff --git a/g10/status.c b/g10/status.c index 32e59eef5..432ec575c 100644 --- a/g10/status.c +++ b/g10/status.c @@ -65,15 +65,15 @@ static FILE *statusfp; static void -progress_cb ( void *ctx, int c ) +progress_cb (void *ctx, const char *what, int printchar, int current, int total) { - char buf[50]; - - if ( c == '\n' ) - sprintf ( buf, "%.20s X 100 100", (char*)ctx ); - else - sprintf ( buf, "%.20s %c 0 0", (char*)ctx, c ); - write_status_text ( STATUS_PROGRESS, buf ); + char buf[150]; + + if (printchar == '\n') + printchar = 'X'; + + sprintf (buf, "%.20s %c %d %d", what, printchar, current, total); + write_status_text (STATUS_PROGRESS, buf); } static const char * @@ -181,12 +181,7 @@ set_status_fd ( int fd ) fd, strerror(errno)); } last_fd = fd; -#warning fixme: register progress CBs -#if 0 - register_primegen_progress ( progress_cb, "primegen" ); - register_pk_dsa_progress ( progress_cb, "pk_dsa" ); - register_pk_elg_progress ( progress_cb, "pk_elg" ); -#endif + gcry_set_progress_handler (progress_cb, NULL); } int