diff --git a/NEWS b/NEWS index f37deb29e..c2271afc4 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,9 @@ Noteworthy changes in version 2.1.0beta3 ----------------------------------------------------- - * Fixed regression in GPG'S secret key export function. + * Fixed regression in GPG's secret key export function. + + * Allow generation of card keys up to 4096 bit. Noteworthy changes in version 2.1.0beta2 (2011-03-08) diff --git a/g10/ChangeLog b/g10/ChangeLog index 67b981387..2f107eb5a 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,11 @@ +2011-06-16 Werner Koch + + * card-util.c (ask_card_keysize): Bump key size limit to 4096. + * call-agent.c (scd_genkey_parm_s): New. + (agent_scd_genkey): Use new struct. + (scd_genkey_cb): Implement chunked mode for KEY-DATA. + (scd_genkey_cb_append_savedbytes): New. + 2011-06-13 Werner Koch * pkglue.c (mpi_from_sexp): Use GCRYMPI_FMT_USG to avoid problems diff --git a/g10/call-agent.c b/g10/call-agent.c index 03ea1685f..5a10dbdb9 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -93,6 +93,13 @@ struct cache_nonce_parm_s }; +struct scd_genkey_parm_s +{ + struct agent_card_genkey_s *cgk; + char *savedbytes; /* Malloced space to save key parameter chunks. */ +}; + + static gpg_error_t learn_status_cb (void *opaque, const char *line); @@ -717,14 +724,43 @@ agent_scd_writekey (int keyno, const char *serialno, +static gpg_error_t +scd_genkey_cb_append_savedbytes (struct scd_genkey_parm_s *parm, + const char *line) +{ + gpg_error_t err = 0; + char *p; + + if (!parm->savedbytes) + { + parm->savedbytes = xtrystrdup (line); + if (!parm->savedbytes) + err = gpg_error_from_syserror (); + } + else + { + p = xtrymalloc (strlen (parm->savedbytes) + strlen (line) + 1); + if (!p) + err = gpg_error_from_syserror (); + else + { + strcpy (stpcpy (p, parm->savedbytes), line); + xfree (parm->savedbytes); + parm->savedbytes = p; + } + } + + return err; +} + /* Status callback for the SCD GENKEY command. */ static gpg_error_t scd_genkey_cb (void *opaque, const char *line) { - struct agent_card_genkey_s *parm = opaque; + struct scd_genkey_parm_s *parm = opaque; const char *keyword = line; int keywordlen; - gpg_error_t rc; + gpg_error_t rc = 0; for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) ; @@ -733,7 +769,7 @@ scd_genkey_cb (void *opaque, const char *line) if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen)) { - parm->fprvalid = unhexify_fpr (line, parm->fpr); + parm->cgk->fprvalid = unhexify_fpr (line, parm->cgk->fpr); } else if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen)) { @@ -745,29 +781,47 @@ scd_genkey_cb (void *opaque, const char *line) while (spacep (line)) line++; - rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL); - if (rc) - log_error ("error parsing received key data: %s\n", gpg_strerror (rc)); - else if (*name == 'n' && spacep (name+1)) - parm->n = a; - else if (*name == 'e' && spacep (name+1)) - parm->e = a; + if (*name == '-' && spacep (name+1)) + rc = scd_genkey_cb_append_savedbytes (parm, line); else { - log_info ("unknown parameter name in received key data\n"); - gcry_mpi_release (a); + if (parm->savedbytes) + { + rc = scd_genkey_cb_append_savedbytes (parm, line); + if (!rc) + rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, + parm->savedbytes, 0, NULL); + } + else + rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL); + if (rc) + log_error ("error parsing received key data: %s\n", + gpg_strerror (rc)); + else if (*name == 'n' && spacep (name+1)) + parm->cgk->n = a; + else if (*name == 'e' && spacep (name+1)) + parm->cgk->e = a; + else + { + log_info ("unknown parameter name in received key data\n"); + gcry_mpi_release (a); + rc = gpg_error (GPG_ERR_INV_PARAMETER); + } + + xfree (parm->savedbytes); + parm->savedbytes = NULL; } } else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen)) { - parm->created_at = (u32)strtoul (line, NULL, 10); + parm->cgk->created_at = (u32)strtoul (line, NULL, 10); } else if (keywordlen == 8 && !memcmp (keyword, "PROGRESS", keywordlen)) { write_status_text (STATUS_PROGRESS, line); } - return 0; + return rc; } /* Send a GENKEY command to the SCdaemon. SERIALNO is not used in @@ -781,9 +835,13 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force, int rc; char line[ASSUAN_LINELENGTH]; gnupg_isotime_t tbuf; + struct scd_genkey_parm_s parms; (void)serialno; + memset (&parms, 0, sizeof parms); + parms.cgk = info; + rc = start_agent (NULL, 1); if (rc) return rc; @@ -802,7 +860,9 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force, memset (info, 0, sizeof *info); rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL, - scd_genkey_cb, info); + scd_genkey_cb, &parms); + + xfree (parms.savedbytes); status_sc_op_failure (rc); return rc; diff --git a/g10/card-util.c b/g10/card-util.c index 0ffb18dd7..9c124bbfc 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -1294,7 +1294,7 @@ static unsigned int ask_card_keysize (int keyno, unsigned int nbits) { unsigned int min_nbits = 1024; - unsigned int max_nbits = 3072; /* GnuPG limit due to Assuan. */ + unsigned int max_nbits = 4096; char *prompt, *answer; unsigned int req_nbits; diff --git a/scd/ChangeLog b/scd/ChangeLog index 0a614c855..9c4d03592 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,9 @@ +2011-06-16 Werner Koch + + * app-openpgp.c (send_key_data): Implemented chunked mode. + (change_keyattr): Increase limit to 4096. + (do_decipher): Adjust padding for 4096 bit keys. + 2011-02-23 Werner Koch * apdu.c (apdu_open_reader): Lock in to CCID if used once. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 660519059..fef17faa9 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -756,20 +756,29 @@ static void send_key_data (ctrl_t ctrl, const char *name, const unsigned char *a, size_t alen) { - char *buf; + char *buffer, *buf; + size_t buflen; - buf = bin2hex (a, alen, NULL); - if (!buf) + buffer = buf = bin2hex (a, alen, NULL); + if (!buffer) { log_error ("memory allocation error in send_key_data\n"); return; } + buflen = strlen (buffer); + /* 768 is the hexified size for the modulus of an 3072 bit key. We + use extra chunks to transmit larger data (i.e for 4096 bit). */ + for ( ;buflen > 768; buflen -= 768, buf += 768) + send_status_info (ctrl, "KEY-DATA", + "-", 1, + buf, 768, + NULL, 0); send_status_info (ctrl, "KEY-DATA", name, (size_t)strlen(name), - buf, (size_t)strlen (buf), + buf, buflen, NULL, 0); - xfree (buf); + xfree (buffer); } @@ -2365,7 +2374,7 @@ change_keyattr (app_t app, int keyno, unsigned int nbits, assert (keyno >=0 && keyno <= 2); - if (nbits > 3072) + if (nbits > 4096) return gpg_error (GPG_ERR_TOO_LARGE); /* Read the current attributes into a buffer. */ @@ -2823,7 +2832,7 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, already lead to a 527 byte long status line and thus a 4096 bit key would exceed the Assuan line length limit. */ keybits = app->app_local->keyattr[keyno].n_bits; - if (keybits > 3072) + if (keybits > 4096) return gpg_error (GPG_ERR_TOO_LARGE); /* Prepare for key generation by verifying the Admin PIN. */ @@ -3377,6 +3386,8 @@ do_decipher (app_t app, const char *keyidstr, fixuplen = 256 - indatalen; else if (indatalen >= (384-16) && indatalen < 384) /* 3072 bit key. */ fixuplen = 384 - indatalen; + else if (indatalen >= (512-16) && indatalen < 512) /* 4096 bit key. */ + fixuplen = 512 - indatalen; else fixuplen = 0; diff --git a/scd/command.c b/scd/command.c index be11ccb77..a579b24eb 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1288,11 +1288,15 @@ static const char hlp_genkey[] = "\n" "Generate a key on-card identified by NO, which is application\n" "specific. Return values are application specific. For OpenPGP\n" - "cards 2 status lines are returned:\n" + "cards 3 status lines are returned:\n" "\n" " S KEY-FPR \n" " S KEY-CREATED-AT \n" - " S KEY-DATA [p|n] \n" + " S KEY-DATA [-|p|n] \n" + "\n" + " 'p' and 'n' are the names of the RSA parameters; '-' is used to\n" + " indicate that HEXDATA is the first chunk of a parameter given\n" + " by the next KEY-DATA.\n" "\n" "--force is required to overwrite an already existing key. The\n" "KEY-CREATED-AT is required for further processing because it is\n"